From 8022c1b1ea2d72ec6dd2fd44adbec3b3d833d4f4 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 2 May 2012 00:45:23 -0500 Subject: [PATCH 01/16] Updating the API to fix some inconsistencies --- doc/Doxyfile | 2 +- include/serial/impl/unix.h | 42 +-- include/serial/serial.h | 386 +++++++++++++++-------- serial.sublime-project | 18 ++ serial.sublime-workspace | 631 +++++++++++++++++++++++++++++++++++++ src/impl/unix.cc | 364 +++++++++++---------- src/serial.cc | 13 +- 7 files changed, 1119 insertions(+), 337 deletions(-) create mode 100644 serial.sublime-project create mode 100644 serial.sublime-workspace diff --git a/doc/Doxyfile b/doc/Doxyfile index f64a659..6b4472f 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -37,7 +37,7 @@ PROJECT_NUMBER = 1.0 # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = Cross-platform serial port library for C++ +PROJECT_BRIEF = "Cross-platform serial port library for C++" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not diff --git a/include/serial/impl/unix.h b/include/serial/impl/unix.h index 98f0fec..2e134df 100644 --- a/include/serial/impl/unix.h +++ b/include/serial/impl/unix.h @@ -10,7 +10,7 @@ * * Copyright (c) 2011 William Woodall, John Harrison * - * Permission is hereby granted, free of charge, to any person obtaining a + * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, @@ -24,8 +24,8 @@ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * \section DESCRIPTION @@ -54,7 +54,6 @@ class serial::Serial::SerialImpl { public: SerialImpl (const string &port, unsigned long baudrate, - long timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, @@ -75,7 +74,7 @@ public: available (); size_t - read (unsigned char* buf, size_t size = 1); + read (unsigned char *buf, size_t size = 1); size_t write (const string &data); @@ -90,28 +89,31 @@ public: flushOutput (); void - sendBreak(int duration); + sendBreak (int duration); void - setBreak(bool level); + setBreak (bool level); void - setRTS(bool level); + setRTS (bool level); void - setDTR(bool level); + setDTR (bool level); bool - getCTS(); + waitForChange (); bool - getDSR(); + getCTS (); bool - getRI(); + getDSR (); bool - getCD(); + getRI (); + + bool + getCD (); void setPort (const string &port); @@ -120,9 +122,9 @@ public: getPort () const; void - setTimeout (long timeout); + setTimeout (timeout_t &timeout); - long + timeout_t getTimeout () const; void @@ -156,16 +158,16 @@ public: getFlowcontrol () const; void - readLock(); + readLock (); void - readUnlock(); + readUnlock (); void - writeLock(); + writeLock (); void - writeUnlock(); + writeUnlock (); protected: void reconfigurePort (); @@ -178,7 +180,7 @@ private: bool xonxoff_; bool rtscts_; - long timeout_; // Timeout for read operations + timeout_t timeout_; // Timeout for read operations unsigned long baudrate_; // Baudrate parity_t parity_; // Parity diff --git a/include/serial/serial.h b/include/serial/serial.h index c1a9269..ad29bab 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -43,7 +43,8 @@ #include #include -#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, __LINE__, (message) ) +#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ +__LINE__, (message) ) namespace serial { @@ -83,27 +84,50 @@ typedef enum { flowcontrol_software } flowcontrol_t; +/*! + * Structure for setting the timeout of the serial port, times are + * in milliseconds. + */ +struct timeout_t { + timeout_t (long inter_byte_timeout_=0, long read_timeout_constant_=0, + long read_timeout_multiplier_=0, long write_timeout_constant_=0, + long write_timeout_multiplier_=0) + : inter_byte_timeout(inter_byte_timeout_), + read_timeout_constant(read_timeout_constant_), + read_timeout_multiplier(read_timeout_multiplier_), + write_timeout_constant(write_timeout_constant_), + write_timeout_multiplier(write_timeout_multiplier_) + {} + /*! Number of milliseconds between bytes received to timeout on. */ + long inter_byte_timeout; + /*! A constant number of milliseconds to wait after calling read. */ + long read_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling read. + */ + long read_timeout_multiplier; + /*! A constant number of milliseconds to wait after calling write. */ + long write_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling write. + */ + long write_timeout_multiplier; +}; + /*! * Class that provides a portable serial port interface. */ class Serial { public: /*! - * Constructor, creates a SerialPortBoost object and opens the port. + * Creates a Serial object and opens the port if a port is specified, + * otherwise it remains closed until serial::Serial::open is called. * * \param port A std::string containing the address of the serial port, * which would be something like 'COM1' on Windows and '/dev/ttyS0' * on Linux. * - * \param baudrate An integer that represents the buadrate - * - * \param timeout A long that represents the time (in milliseconds) until a - * timeout on reads occur. Setting this to zero (0) will cause reading to - * be non-blocking, i.e. the available data will be returned immediately, - * but it will not block to wait for more. Setting this to a number less - * than zero (-1) will result in infinite blocking behaviour, i.e. the - * serial port will block until either size bytes have been read or an - * exception has occured. + * \param baudrate An integer that represents the baudrate * * \param bytesize Size of each byte in the serial transmission of data, * default is eightbits, possible values are: fivebits, sixbits, sevenbits, @@ -119,14 +143,10 @@ public: * flowcontrol_none, possible values are: flowcontrol_none, * flowcontrol_software, flowcontrol_hardware * - * \param buffer_size The maximum size of the internal buffer, defaults - * to 256 bytes (2^8). - * * \throw PortNotOpenedException */ Serial (const std::string &port = "", unsigned long baudrate = 9600, - long timeout = 0, bytesize_t bytesize = eightbits, parity_t parity = parity_none, stopbits_t stopbits = stopbits_one, @@ -136,8 +156,8 @@ public: virtual ~Serial (); /*! - * Opens the serial port as long as the portname is set and the port isn't - * alreay open. + * Opens the serial port as long as the port is set and the port isn't + * already open. * * If the port is provided to the constructor then an explicit call to open * is not needed. @@ -164,28 +184,82 @@ public: /*! Return the number of characters in the buffer. */ size_t - available(); + available (); - /*! Read a given amount of bytes from the serial port. - * - * If a timeout is set it may return less characters than requested. With - * no timeout it will block until the requested number of bytes have been - * read or until an exception occurs. + /*! Read a given amount of bytes from the serial port into a given buffer. * + * The read function will return in one of three cases: + * * The number of requested bytes was read. + * * In this case the number of bytes requested will match the size_t + * returned by read. + * * A timeout occurred, in this case the number of bytes read will not + * match the amount requested, but no exception will be thrown. One of + * two possible timeouts occurred: + * * The inter byte timeout expired, this means that number of + * milliseconds elapsed between receiving bytes from the serial port + * exceeded the inter byte timeout. + * * The total timeout expired, which is calculated by multiplying the + * read timeout multiplier by the number of requested bytes and then + * added to the read timeout constant. If that total number of + * milliseconds elapses after the initial call to read a timeout will + * occur. + * * An exception occurred, in this case an actual exception will be thrown. + * + * \param buffer An unsigned char array of at least the requested size. * \param size A size_t defining how many bytes to be read. * - * \return A std::string containing the data read. + * \return A size_t representing the number of bytes read as a result of the + * call to read. */ size_t read (unsigned char *buffer, size_t size); + + /*! Read a given amount of bytes from the serial port into a give buffer. + * + * \param buffer A reference to a std::vector of unsigned char. + * \param size A size_t defining how many bytes to be read. + * + * \return A size_t representing the number of bytes read as a result of the + * call to read. + */ size_t read (std::vector &buffer, size_t size = 1); + + /*! Read a given amount of bytes from the serial port into a give buffer. + * + * \param buffer A reference to a std::string. + * \param size A size_t defining how many bytes to be read. + * + * \return A size_t representing the number of bytes read as a result of the + * call to read. + */ size_t read (std::string &buffer, size_t size = 1); + + /*! Read a given amount of bytes from the serial port and return a string + * containing the data. + * + * \param size A size_t defining how many bytes to be read. + * + * \return A std::string containing the data read from the port. + */ std::string read (size_t size = 1); - /*! Reads in a line or until a given delimiter has been processed + /*! Reads in a line or until a given delimiter has been processed. + * + * Reads from the serial port until a single line has been read. + * + * \param buffer A std::string reference used to store the data. + * \param size A maximum length of a line, defaults to 65536 (2^16) + * \param eol A string to match against for the EOL. + * + * \return A size_t representing the number of bytes read. + */ + size_t + readline (std::string &buffer, size_t size = 65536, std::string eol = "\n"); + + /*! Reads in a line or until a given delimiter has been processed. * * Reads from the serial port until a single line has been read. * @@ -194,15 +268,10 @@ public: * * \return A std::string containing the line. */ - size_t - readline (std::string &buffer, - size_t size = 65536, - std::string eol = "\n"); std::string - readline (size_t size = 65536, - std::string eol = "\n"); + readline (size_t size = 65536, std::string eol = "\n"); - /*! Reads in multiple lines until the serail port times out. + /*! Reads in multiple lines until the serial port times out. * * This requires a timeout > 0 before it can be run. It will read until a * timeout occurs and return a list of strings. @@ -218,160 +287,207 @@ public: /*! Write a string to the serial port. * - * \param data A const reference containg the data to be written + * \param data A const reference containing the data to be written * to the serial port. * + * \param size A size_t that indicates how many bytes should be written from + * the given data buffer. + * * \return A size_t representing the number of bytes actually written to * the serial port. */ size_t write (const unsigned char *data, size_t size); + + /*! Write a string to the serial port. + * + * \param data A const reference containing the data to be written + * to the serial port. + * + * \return A size_t representing the number of bytes actually written to + * the serial port. + */ size_t write (const std::vector &data); + + /*! Write a string to the serial port. + * + * \param data A const reference containing the data to be written + * to the serial port. + * + * \return A size_t representing the number of bytes actually written to + * the serial port. + */ size_t write (const std::string &data); /*! Sets the serial port identifier. - * - * \param port A const std::string reference containing the address of the - * serial port, which would be something like 'COM1' on Windows and - * '/dev/ttyS0' on Linux. - * - * \throw InvalidConfigurationException - */ + * + * \param port A const std::string reference containing the address of the + * serial port, which would be something like 'COM1' on Windows and + * '/dev/ttyS0' on Linux. + * + * \throw InvalidConfigurationException + */ void setPort (const std::string &port); /*! Gets the serial port identifier. - * - * \see Serial::setPort - * - * \throw InvalidConfigurationException - */ + * + * \see Serial::setPort + * + * \throw InvalidConfigurationException + */ std::string getPort () const; - /*! Sets the timeout for reads in milliseconds. - * - * \param timeout A long that represents the time (in milliseconds) until a - * timeout on reads occur. Setting this to zero (0) will cause reading to be - * non-blocking, i.e. the available data will be returned immediately, but it - * will not block to wait for more. Setting this to a number less than - * zero (-1) will result in infinite blocking behaviour, i.e. the serial port - * will block until either size bytes have been read or an exception has - * occured. - */ + /*! Sets the timeout for reads and writes using the timeout_t struct. + * + * There are two basic conditions for timeout described here, the inter byte + * timeout is the maximum amount of time in milliseconds allowed between + * receiving bytes from the serial port. The second condition is where the + * total timeout expires during a read or write. The total timeout can be + * calculated as the multiplier times the number of requested bytes plus the + * constant. In this way a single constant time timeout can be specified + * with zero for the inter byte timeout and zero for the multiplier. + * Alternatively, you could have only an inter byte timeout and zero for + * both the constant and multiplier to prevent a total time timeout from + * occurring.You can use the multiplier to increase the total time timeout + * based on the number of bytes requested. The user can combine any of + * these timeout metrics in order to achieve the desired trade-off between + * efficiency and responsiveness. + * + * \param timeout A timeout_t struct containing the inter byte timeout, and + * the read and write timeout constants and multipliers. + * + * \see serial::timeout_t + */ void - setTimeout (long timeout); + setTimeout (timeout_t &timeout); + + /*! Sets the timeout for reads and writes. */ + void + setTimeout (long inter_byte_timeout, long read_timeout_constant, + long read_timeout_multiplier, long write_timeout_constant, + long write_timeout_multiplier) + { + timeout_t timeout(inter_byte_timeout, read_timeout_constant, + read_timeout_multiplier, write_timeout_constant, + write_timeout_multiplier); + return setTimeout(timeout); + } /*! Gets the timeout for reads in seconds. - * - * \see Serial::setTimeout - */ - long + * + * \return A timeout_t struct containing the inter_byte_timeout, and read + * and write timeout constants and multipliers. + * + * \see Serial::setTimeout + */ + timeout_t getTimeout () const; /*! Sets the baudrate for the serial port. - * - * Possible baudrates depends on the system but some safe baudrates include: - * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, - * 57600, 115200 - * Some other baudrates that are supported by some comports: - * 128000, 153600, 230400, 256000, 460800, 921600 - * - * \param baudrate An integer that sets the baud rate for the serial port. - * - * \throw InvalidConfigurationException - */ + * + * Possible baudrates depends on the system but some safe baudrates include: + * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, + * 57600, 115200 + * Some other baudrates that are supported by some comports: + * 128000, 153600, 230400, 256000, 460800, 921600 + * + * \param baudrate An integer that sets the baud rate for the serial port. + * + * \throw InvalidConfigurationException + */ void setBaudrate (unsigned long baudrate); /*! Gets the baudrate for the serial port. - * - * \return An integer that sets the baud rate for the serial port. - * - * \see Serial::setBaudrate - * - * \throw InvalidConfigurationException - */ + * + * \return An integer that sets the baud rate for the serial port. + * + * \see Serial::setBaudrate + * + * \throw InvalidConfigurationException + */ unsigned long getBaudrate () const; /*! Sets the bytesize for the serial port. - * - * \param bytesize Size of each byte in the serial transmission of data, - * default is eightbits, possible values are: fivebits, sixbits, sevenbits, - * eightbits - * - * \throw InvalidConfigurationException - */ + * + * \param bytesize Size of each byte in the serial transmission of data, + * default is eightbits, possible values are: fivebits, sixbits, sevenbits, + * eightbits + * + * \throw InvalidConfigurationException + */ void setBytesize (bytesize_t bytesize); /*! Gets the bytesize for the serial port. - * - * \see Serial::setBytesize - * - * \throw InvalidConfigurationException - */ + * + * \see Serial::setBytesize + * + * \throw InvalidConfigurationException + */ bytesize_t getBytesize () const; /*! Sets the parity for the serial port. - * - * \param parity Method of parity, default is parity_none, possible values - * are: parity_none, parity_odd, parity_even - * - * \throw InvalidConfigurationException - */ + * + * \param parity Method of parity, default is parity_none, possible values + * are: parity_none, parity_odd, parity_even + * + * \throw InvalidConfigurationException + */ void setParity (parity_t parity); /*! Gets the parity for the serial port. - * - * \see Serial::setParity - * - * \throw InvalidConfigurationException - */ + * + * \see Serial::setParity + * + * \throw InvalidConfigurationException + */ parity_t getParity () const; /*! Sets the stopbits for the serial port. - * - * \param stopbits Number of stop bits used, default is stopbits_one, - * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two - * - * \throw InvalidConfigurationException - */ + * + * \param stopbits Number of stop bits used, default is stopbits_one, + * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two + * + * \throw InvalidConfigurationException + */ void setStopbits (stopbits_t stopbits); /*! Gets the stopbits for the serial port. - * - * \see Serial::setStopbits - * - * \throw InvalidConfigurationException - */ + * + * \see Serial::setStopbits + * + * \throw InvalidConfigurationException + */ stopbits_t getStopbits () const; /*! Sets the flow control for the serial port. - * - * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, - * possible values are: flowcontrol_none, flowcontrol_software, - * flowcontrol_hardware - * - * \throw InvalidConfigurationException - */ + * + * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, + * possible values are: flowcontrol_none, flowcontrol_software, + * flowcontrol_hardware + * + * \throw InvalidConfigurationException + */ void setFlowcontrol (flowcontrol_t flowcontrol); /*! Gets the flow control for the serial port. - * - * \see Serial::setFlowcontrol - * - * \throw InvalidConfigurationException - */ + * + * \see Serial::setFlowcontrol + * + * \throw InvalidConfigurationException + */ flowcontrol_t getFlowcontrol () const; @@ -387,27 +503,49 @@ public: void flushOutput (); + /*! Sends the RS-232 break signal. See tcsendbreak(3). */ void sendBreak (int duration); + /*! Set the break condition to a given level. Defaults to true. */ void setBreak (bool level = true); + /*! Set the RTS handshaking line to the given level. Defaults to true. */ void setRTS (bool level = true); + /*! Set the DTR handshaking line to the given level. Defaults to true. */ void setDTR (bool level = true); + /*! + * Returns true on CTS, DSR, RI, or CD changing. + * + * Can throw an exception if an error occurs while waiting. + * You can check the status of CTS, DSR, RI, and CD once this returns. + * Uses TIOCMIWAIT via ioctl if available (mostly only on Linux) with a + * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a + * polling method is used which can give +-2ms. + * + * \throw SerialException + */ + bool + waitForChange (); + + /*! Returns the current status of the CTS line. */ bool getCTS (); + /*! Returns the current status of the DSR line. */ bool getDSR (); + /*! Returns the current status of the RI line. */ bool getRI (); + /*! Returns the current status of the CD line. */ bool getCD (); diff --git a/serial.sublime-project b/serial.sublime-project new file mode 100644 index 0000000..1746fa9 --- /dev/null +++ b/serial.sublime-project @@ -0,0 +1,18 @@ +{ + "folders": + [ + { + "path": "/Users/william/devel/serial" + } + ], + "settings": + { + "sublimeclang_options": + [ + "-I/usr/include", + "-I/usr/local/include", + "-I/usr/lib/clang/3.1/include/", + "-I${folder:${project_path:serial.sublime-project}}/include" + ] + } +} diff --git a/serial.sublime-workspace b/serial.sublime-workspace new file mode 100644 index 0000000..486d099 --- /dev/null +++ b/serial.sublime-workspace @@ -0,0 +1,631 @@ +{ + "auto_complete": + { + "selected_items": + [ + [ + "tour", + "toupper(int _c) int" + ], + [ + "rotat", + "SceneObject::rotateTo(GLfloat roll, GLfloat pitch, GLfloat yaw) void" + ], + [ + "tou", + "touring_index size_t" + ], + [ + "person", + "person_mbb Model::CollisionBox" + ], + [ + "SE", + "SE Model::CollisionBox" + ], + [ + "m", + "mbb Model::CollisionBox" + ], + [ + "glVer", + "glVertex2fv(const GLfloat *v) void" + ], + [ + "di", + "distance GLfloat" + ], + [ + "the", + "their_position GLfloat *" + ], + [ + "their", + "their_obj_it vector::iterator" + ], + [ + "my", + "my_obj_it vector::iterator" + ], + [ + "my_mod", + "my_model_it vector::iterator" + ], + [ + "thei", + "their_model_it vector::iterator" + ], + [ + "iterator", + "assign(_InputIterator __first, _InputIterator __last) void" + ], + [ + "get", + "getPosition() GLfloat *" + ], + [ + "lh", + "lhs_mbb Model::CollisionBox" + ], + [ + "cal", + "calculateMBB(Model::Object &obj) Model::CollisionBox" + ], + [ + "Col", + "CollisionBox " + ], + [ + "spo", + "spotlight LightingStyle" + ], + [ + "main", + "main_camera Camera" + ], + [ + "pers", + "person Person *" + ], + [ + "glro", + "glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) void" + ], + [ + "glTran", + "glTranslatef(GLfloat x, GLfloat y, GLfloat z) void" + ], + [ + "she", + "shelby_model string" + ], + [ + "loa", + "loaded_ bool" + ], + [ + "ena", + "enabled_ bool" + ], + [ + "sp", + "specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a) void" + ], + [ + "en", + "direction(GLfloat x, GLfloat y, GLfloat z) void" + ], + [ + "spot", + "spot_light Light" + ], + [ + "GL_NOR", + "GL_NORMALIZE " + ], + [ + "att", + "attenuation_q_ GLfloat" + ], + [ + "atte", + "attenuation_c_ GLfloat" + ], + [ + "glPop", + "glPopMatrix() void" + ], + [ + "appl", + "apply_() void" + ], + [ + "no_l", + "no_lights_left const size_t" + ], + [ + "ligh", + "lights_left size_t" + ], + [ + "do", + "do_normals bool" + ], + [ + "back_in", + "back_inserter(_Container &__x) back_insert_iterator<_Container>" + ], + [ + "istr", + "istream_iterator " + ], + [ + "is", + "istringstream " + ], + [ + "math", + "matches size_t" + ], + [ + "curr", + "current_object Model::Object" + ], + [ + "matc", + "matches2 size_t" + ], + [ + "QwtPlot", + "QwtPlotZoomer" + ], + [ + "__init", + "__initZooming" + ], + [ + "plot_coi", + "plot_coil2" + ], + [ + "plo", + "plot_coil1" + ], + [ + "plot_co", + "plot_coil2" + ], + [ + "QwtPl", + "QwtPlotCurve" + ], + [ + "trail", + "trailer_plotcurve" + ], + [ + "pl", + "plot_coil1" + ], + [ + "plot", + "plot_coil1" + ], + [ + "open", + "open_button" + ], + [ + "plotcoi", + "plot_coil1" + ], + [ + "EM", + "EM61MK2Log" + ], + [ + "pa", + "path_file_name" + ], + [ + "head", + "headings" + ], + [ + "eas", + "eastings" + ], + [ + "north", + "northings" + ], + [ + "las", + "last_east" + ], + [ + "odom", + "odom" + ], + [ + "logs", + "logs_data" + ], + [ + "plot_", + "plot_em61mk2logs" + ], + [ + "Em61", + "EM61MK2Log" + ], + [ + "sib", + "sibling_file_name" + ], + [ + "si", + "sibling_file_name" + ], + [ + "fil", + "file_name" + ] + ] + }, + "buffers": + [ + { + "file": "include/serial/serial.h", + "settings": + { + "buffer_size": 17876, + "line_ending": "Unix" + } + }, + { + "file": "src/serial.cc", + "settings": + { + "buffer_size": 7015, + "line_ending": "Unix" + } + }, + { + "file": "src/impl/unix.cc", + "settings": + { + "buffer_size": 16696, + "line_ending": "Unix" + } + } + ], + "build_system": "Packages/Python/Python.sublime-build", + "command_palette": + { + "height": 47.0, + "selected_items": + [ + [ + "install", + "Package Control: Install Package" + ], + [ + "late", + "LaTeXTools: View PDF" + ] + ], + "width": 449.0 + }, + "console": + { + "height": 0.0 + }, + "distraction_free": + { + "menu_visible": true, + "show_minimap": false, + "show_open_files": false, + "show_tabs": false, + "side_bar_visible": false, + "status_bar_visible": false + }, + "file_history": + [ + "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", + "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py", + "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py", + "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/survey.csv", + "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/image_generator.py", + "/Users/william/.ros/rosdep.yaml", + "/Users/william/.bashrc", + "/Users/william/devel/xbow400/include/xbow_400.h", + "/Users/william/devel/xbow400/src/xbow_400.cpp", + "/Users/william/devel/xbow400/README", + "/Users/william/devel/xbow400/xbow400.sublime-project", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", + "/Users/william/devel/comp6400/homework6/homework6.sublime-project", + "/Users/william/devel/comp6400/homework6/src/main.cc", + "/Users/william/devel/comp6400/homework6/models/student.obj", + "/Users/william/devel/comp6400/homework6/models/ground.obj", + "/Users/william/devel/comp6400/homework6/models/shelby.obj", + "/Users/william/devel/comp6400/homework6/models/ground.mtl", + "/Users/william/devel/comp6400/homework6/models/shelby.mtl", + "/Users/william/devel/comp6400/homework6/CMakeLists.txt", + "/Users/william/devel/comp6400/homework6/models/shelby.blend", + "/Users/william/devel/comp6400/homework6/Makefile", + "/usr/include/c++/4.2.1/tr1/cstdio", + "/Users/william/devel/comp6400/homework6/src/michaels.cc", + "/Users/william/devel/auxos_orig/scripts/plot_em.py", + "/Users/william/devel/auxos_orig/scripts/logtool.py", + "/Users/william/devel/auxos_orig/scripts/em61mk2.py", + "/Users/william/devel/auxos_orig/scripts/lib/__init__.py", + "/usr/local/Library/Formula/pyqt.rb", + "/usr/local/Library/Formula/pyqwt.rb", + "/Users/william/devel/3dteleop_ws/3d_teleop/redo_slam_offline/launch/play_and_remap_tf.launch", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/launch/automow_stuff.launch", + "/Users/william/devel/auxos_orig/scripts/coords2path.py", + "/Users/william/Downloads/sup1_waypts_utm_path.txt", + "/Users/william/Downloads/example.txt", + "/Users/william/devel/auxos_orig/scripts/sup1_waypts_utm_path.txt", + "/Users/william/devel/ion_plans_paper/citations.bib", + "/Users/william/devel/ion_plans_paper/ion_plans.tex", + "/Users/william/Desktop/em61mk2.py", + "/Users/william/devel/ion_plans_paper/ion_plans.log", + "/Users/william/devel/ion_plans_paper/ion_plans.pdf", + "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OcTree.h", + "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.h", + "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.hxx", + "/Users/william/devel/3dteleop_ws/octomap/octomap/src/OcTree.cpp", + "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/octomap_deprecated.h", + "/Users/william/devel/3dteleop_ws/octomap/CMakeLists.txt", + "/Users/william/devel/comp6400/homework3/src/main.cc", + "/Users/william/Desktop/untitled.obj", + "/Users/william/devel/cs373-tests/util.py", + "/Users/william/devel/cs373-tests/2.6/code.py", + "/Users/william/devel/cs373-tests/2.6/template.py", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/manifest.xml", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/odom2tf.py", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/automow_laser_filter.py", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/rename_tf_frame.py", + "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/remap_tf.py", + "/Users/william/Downloads/orocos_kinematics_dynamics-ffdeaad-install_name_tool.patch", + "/Users/william/devel/automow_ws/au_automow_common/automow_bringup/launch/minimal.launch", + "/Users/william/devel/vis_ws/visualization/rviz/manifest.xml", + "/Library/Python/2.7/site-packages/pkg_resources.py", + "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", + "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/plot_em61mk2.py", + "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/em61mk2.py", + "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/em61mk2.py", + "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/plot_em61mk2.py" + ], + "find": + { + "height": 35.0 + }, + "find_in_files": + { + "height": 0.0, + "where_history": + [ + "" + ] + }, + "find_state": + { + "case_sensitive": false, + "find_history": + [ + "cts", + " ", + "o ", + "Cube_Cube.001", + "min[2]", + "min[1]", + "max[2]", + "max[1]", + "max[0]", + "min[0]", + "window_width", + "800", + "•", + "Cube", + "expected 1.", + "counter", + "go", + "setZoomerMousePattern", + "updateNode", + "compute", + "insertS" + ], + "highlight": true, + "in_selection": false, + "preserve_case": false, + "regex": false, + "replace_history": + [ + ", ", + "min.z", + "min.y", + "max.z", + "max.y", + "max.x", + "min.x", + "*" + ], + "reverse": false, + "show_context": true, + "use_buffer2": true, + "whole_word": false, + "wrap": true + }, + "groups": + [ + { + "selected": 2, + "sheets": + [ + { + "buffer": 0, + "file": "include/serial/serial.h", + "settings": + { + "buffer_size": 17876, + "regions": + { + }, + "selection": + [ + [ + 11407, + 11407 + ] + ], + "settings": + { + "syntax": "Packages/C++/C++.tmLanguage", + "tab_size": 4, + "translate_tabs_to_spaces": true, + "word_wrap": true, + "wrap_width": 80 + }, + "translation.x": 0.0, + "translation.y": 6934.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 1, + "file": "src/serial.cc", + "settings": + { + "buffer_size": 7015, + "regions": + { + }, + "selection": + [ + [ + 0, + 0 + ] + ], + "settings": + { + "syntax": "Packages/C++/C++.tmLanguage", + "tab_size": 2, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 479.0, + "zoom_level": 1.0 + }, + "type": "text" + }, + { + "buffer": 2, + "file": "src/impl/unix.cc", + "settings": + { + "buffer_size": 16696, + "regions": + { + }, + "selection": + [ + [ + 15521, + 15521 + ] + ], + "settings": + { + "syntax": "Packages/C++/C++.tmLanguage", + "tab_size": 2, + "translate_tabs_to_spaces": true + }, + "translation.x": 0.0, + "translation.y": 10013.0, + "zoom_level": 1.0 + }, + "type": "text" + } + ] + }, + { + "sheets": + [ + ] + } + ], + "incremental_find": + { + "height": 0.0 + }, + "input": + { + "height": 31.0 + }, + "layout": + { + "cells": + [ + [ + 0, + 0, + 1, + 1 + ], + [ + 1, + 0, + 2, + 1 + ] + ], + "cols": + [ + 0.0, + 0.61784814072, + 1.0 + ], + "rows": + [ + 0.0, + 1.0 + ] + }, + "menu_visible": true, + "output.clang": + { + "height": 100.0 + }, + "replace": + { + "height": 64.0 + }, + "save_all_on_build": true, + "select_file": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "select_project": + { + "height": 0.0, + "selected_items": + [ + ], + "width": 0.0 + }, + "show_minimap": false, + "show_open_files": false, + "show_tabs": true, + "side_bar_visible": true, + "side_bar_width": 283.0, + "status_bar_visible": true +} diff --git a/src/impl/unix.cc b/src/impl/unix.cc index e87125d..e8d0f4c 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -2,9 +2,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -35,6 +37,7 @@ #endif using std::string; +using std::stringstream; using std::invalid_argument; using serial::Serial; using serial::SerialExecption; @@ -43,12 +46,12 @@ using serial::IOException; Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - long timeout, bytesize_t bytesize, + bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) -: port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (true), rtscts_ (false), - timeout_ (timeout), baudrate_ (baudrate), parity_ (parity), - bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) + : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (true), rtscts_ (false), + baudrate_ (baudrate), parity_ (parity), + bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) { pthread_mutex_init(&this->read_mutex, NULL); pthread_mutex_init(&this->write_mutex, NULL); @@ -66,30 +69,26 @@ Serial::SerialImpl::~SerialImpl () void Serial::SerialImpl::open () { - if (port_.empty ()) - { + if (port_.empty ()) { throw invalid_argument ("Empty port is invalid."); } - if (is_open_ == true) - { + if (is_open_ == true) { throw SerialExecption ("Serial port already open."); } fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - if (fd_ == -1) - { - switch (errno) - { - case EINTR: - // Recurse because this is a recoverable error. - open (); - return; - case ENFILE: - case EMFILE: - THROW (IOException, "Too many file handles open."); - default: - THROW (IOException, errno); + if (fd_ == -1) { + switch (errno) { + case EINTR: + // Recurse because this is a recoverable error. + open (); + return; + case ENFILE: + case EMFILE: + THROW (IOException, "Too many file handles open."); + default: + THROW (IOException, errno); } } @@ -100,26 +99,24 @@ Serial::SerialImpl::open () void Serial::SerialImpl::reconfigurePort () { - if (fd_ == -1) - { + if (fd_ == -1) { // Can only operate on a valid file descriptor THROW (IOException, "Invalid file descriptor, is the serial port open?"); } struct termios options; // The options for the file descriptor - if (tcgetattr(fd_, &options) == -1) - { + if (tcgetattr(fd_, &options) == -1) { THROW (IOException, "::tcgetattr"); } // set up raw mode / no echo / binary - options.c_cflag |= (unsigned long) (CLOCAL|CREAD); - options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL| - ISIG|IEXTEN); //|ECHOPRT + options.c_cflag |= (unsigned long) (CLOCAL | CREAD); + options.c_lflag &= (unsigned long) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | + ISIG | IEXTEN); //|ECHOPRT options.c_oflag &= (unsigned long) ~(OPOST); - options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK); + options.c_iflag &= (unsigned long) ~(INLCR | IGNCR | ICRNL | IGNBRK); #ifdef IUCLC options.c_iflag &= (unsigned long) ~IUCLC; #endif @@ -130,122 +127,118 @@ Serial::SerialImpl::reconfigurePort () // setup baud rate bool custom_baud = false; speed_t baud; - switch (baudrate_) - { + switch (baudrate_) { #ifdef B0 - case 0: baud = B0; break; + case 0: baud = B0; break; #endif #ifdef B50 - case 50: baud = B50; break; + case 50: baud = B50; break; #endif #ifdef B75 - case 75: baud = B75; break; + case 75: baud = B75; break; #endif #ifdef B110 - case 110: baud = B110; break; + case 110: baud = B110; break; #endif #ifdef B134 - case 134: baud = B134; break; + case 134: baud = B134; break; #endif #ifdef B150 - case 150: baud = B150; break; + case 150: baud = B150; break; #endif #ifdef B200 - case 200: baud = B200; break; + case 200: baud = B200; break; #endif #ifdef B300 - case 300: baud = B300; break; + case 300: baud = B300; break; #endif #ifdef B600 - case 600: baud = B600; break; + case 600: baud = B600; break; #endif #ifdef B1200 - case 1200: baud = B1200; break; + case 1200: baud = B1200; break; #endif #ifdef B1800 - case 1800: baud = B1800; break; + case 1800: baud = B1800; break; #endif #ifdef B2400 - case 2400: baud = B2400; break; + case 2400: baud = B2400; break; #endif #ifdef B4800 - case 4800: baud = B4800; break; + case 4800: baud = B4800; break; #endif #ifdef B7200 - case 7200: baud = B7200; break; + case 7200: baud = B7200; break; #endif #ifdef B9600 - case 9600: baud = B9600; break; + case 9600: baud = B9600; break; #endif #ifdef B14400 - case 14400: baud = B14400; break; + case 14400: baud = B14400; break; #endif #ifdef B19200 - case 19200: baud = B19200; break; + case 19200: baud = B19200; break; #endif #ifdef B28800 - case 28800: baud = B28800; break; + case 28800: baud = B28800; break; #endif #ifdef B57600 - case 57600: baud = B57600; break; + case 57600: baud = B57600; break; #endif #ifdef B76800 - case 76800: baud = B76800; break; + case 76800: baud = B76800; break; #endif #ifdef B38400 - case 38400: baud = B38400; break; + case 38400: baud = B38400; break; #endif #ifdef B115200 - case 115200: baud = B115200; break; + case 115200: baud = B115200; break; #endif #ifdef B128000 - case 128000: baud = B128000; break; + case 128000: baud = B128000; break; #endif #ifdef B153600 - case 153600: baud = B153600; break; + case 153600: baud = B153600; break; #endif #ifdef B230400 - case 230400: baud = B230400; break; + case 230400: baud = B230400; break; #endif #ifdef B256000 - case 256000: baud = B256000; break; + case 256000: baud = B256000; break; #endif #ifdef B460800 - case 460800: baud = B460800; break; + case 460800: baud = B460800; break; #endif #ifdef B921600 - case 921600: baud = B921600; break; + case 921600: baud = B921600; break; #endif - default: - custom_baud = true; -// Mac OS X 10.x Support + default: + custom_baud = true; + // Mac OS X 10.x Support #if defined(__APPLE__) && defined(__MACH__) #define IOSSIOSPEED _IOW('T', 2, speed_t) - int new_baud = static_cast (baudrate_); - if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) - { - THROW (IOException, errno); - } -// Linux Support + int new_baud = static_cast (baudrate_); + if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) { + THROW (IOException, errno); + } + // Linux Support #elif defined(__linux__) - struct serial_struct ser; - ioctl (fd_, TIOCGSERIAL, &ser); - // set custom divisor - ser.custom_divisor = ser.baud_base / baudrate_; - // update flags - ser.flags &= ~ASYNC_SPD_MASK; - ser.flags |= ASYNC_SPD_CUST; + struct serial_struct ser; + ioctl (fd_, TIOCGSERIAL, &ser); + // set custom divisor + ser.custom_divisor = ser.baud_base / baudrate_; + // update flags + ser.flags &= ~ASYNC_SPD_MASK; + ser.flags |= ASYNC_SPD_CUST; - if (ioctl (fd_, TIOCSSERIAL, ser) < 0) - { - THROW (IOException, errno); - } + if (ioctl (fd_, TIOCSSERIAL, ser) < 0) { + THROW (IOException, errno); + } #else - throw invalid_argument ("OS does not currently support custom bauds"); + throw invalid_argument ("OS does not currently support custom bauds"); #endif } - if (custom_baud == false) - { + if (custom_baud == false) { #ifdef _BSD_SOURCE ::cfsetspeed(&options, baud); #else @@ -257,56 +250,49 @@ Serial::SerialImpl::reconfigurePort () // setup char len options.c_cflag &= (unsigned long) ~CSIZE; if (bytesize_ == eightbits) - options.c_cflag |= CS8; + options.c_cflag |= CS8; else if (bytesize_ == sevenbits) - options.c_cflag |= CS7; + options.c_cflag |= CS7; else if (bytesize_ == sixbits) - options.c_cflag |= CS6; + options.c_cflag |= CS6; else if (bytesize_ == fivebits) - options.c_cflag |= CS5; + options.c_cflag |= CS5; else - throw invalid_argument ("invalid char len"); + throw invalid_argument ("invalid char len"); // setup stopbits if (stopbits_ == stopbits_one) - options.c_cflag &= (unsigned long) ~(CSTOPB); + options.c_cflag &= (unsigned long) ~(CSTOPB); else if (stopbits_ == stopbits_one_point_five) - // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 - options.c_cflag |= (CSTOPB); + // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 + options.c_cflag |= (CSTOPB); else if (stopbits_ == stopbits_two) - options.c_cflag |= (CSTOPB); + options.c_cflag |= (CSTOPB); else - throw invalid_argument ("invalid stop bit"); + throw invalid_argument ("invalid stop bit"); // setup parity - options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP); - if (parity_ == parity_none) - { - options.c_cflag &= (unsigned long) ~(PARENB|PARODD); - } - else if (parity_ == parity_even) - { + options.c_iflag &= (unsigned long) ~(INPCK | ISTRIP); + if (parity_ == parity_none) { + options.c_cflag &= (unsigned long) ~(PARENB | PARODD); + } else if (parity_ == parity_even) { options.c_cflag &= (unsigned long) ~(PARODD); options.c_cflag |= (PARENB); - } - else if (parity_ == parity_odd) - { - options.c_cflag |= (PARENB|PARODD); - } - else - { + } else if (parity_ == parity_odd) { + options.c_cflag |= (PARENB | PARODD); + } else { throw invalid_argument ("invalid parity"); } // setup flow control // xonxoff #ifdef IXANY if (xonxoff_) - options.c_iflag |= (IXON|IXOFF); //|IXANY) + options.c_iflag |= (IXON | IXOFF); //|IXANY) else - options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY); + options.c_iflag &= (unsigned long) ~(IXON | IXOFF | IXANY); #else if (xonxoff_) - options.c_iflag |= (IXON|IXOFF); + options.c_iflag |= (IXON | IXOFF); else - options.c_iflag &= (unsigned long) ~(IXON|IXOFF); + options.c_iflag &= (unsigned long) ~(IXON | IXOFF); #endif // rtscts #ifdef CRTSCTS @@ -324,8 +310,8 @@ Serial::SerialImpl::reconfigurePort () #endif // http://www.unixwiz.net/techtips/termios-vmin-vtime.html - // this basically sets the read call up to be a polling read, - // but we are using select to ensure there is data available + // this basically sets the read call up to be a polling read, + // but we are using select to ensure there is data available // to read before each call, so we should never needlessly poll options.c_cc[VMIN] = 0; options.c_cc[VTIME] = 0; @@ -337,10 +323,8 @@ Serial::SerialImpl::reconfigurePort () void Serial::SerialImpl::close () { - if (is_open_ == true) - { - if (fd_ != -1) - { + if (is_open_ == true) { + if (fd_ != -1) { ::close (fd_); // Ignoring the outcome fd_ = -1; } @@ -357,23 +341,20 @@ Serial::SerialImpl::isOpen () const size_t Serial::SerialImpl::available () { - if (!is_open_) - { + if (!is_open_) { return 0; } int count = 0; int result = ioctl (fd_, TIOCINQ, &count); - if (result == 0) - { + if (result == 0) { return static_cast (count); - } - else - { + } else { THROW (IOException, errno); } } -inline void get_time_now(struct timespec &time) { +inline void get_time_now(struct timespec &time) +{ # ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time clock_serv_t cclock; mach_timespec_t mts; @@ -388,23 +369,22 @@ inline void get_time_now(struct timespec &time) { } size_t -Serial::SerialImpl::read (unsigned char* buf, size_t size) +Serial::SerialImpl::read (unsigned char *buf, size_t size) { - if (!is_open_) - { + if (!is_open_) { throw PortNotOpenedException ("Serial::read"); } fd_set readfds; size_t bytes_read = 0; struct timeval timeout; - timeout.tv_sec = timeout_ / 1000; - timeout.tv_usec = static_cast (timeout_ % 1000) * 1000; - while (bytes_read < size) - { + timeout.tv_sec = timeout_.read_timeout_constant / 1000; + timeout.tv_usec = static_cast (timeout_.read_timeout_constant % 1000); + timeout.tv_usec *= 1000; // To convert to micro seconds + while (bytes_read < size) { FD_ZERO (&readfds); FD_SET (fd_, &readfds); - // On Linux the timeout struct is updated by select to contain the time - // left on the timeout to make looping easier, but on other platforms this + // On Linux the timeout struct is updated by select to contain the time + // left on the timeout to make looping easier, but on other platforms this // does not occur. #if !defined(__linux__) // Begin timing select @@ -418,8 +398,8 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size) get_time_now(end); // Calculate the time select took struct timeval diff; - diff.tv_sec = end.tv_sec-start.tv_sec; - diff.tv_usec = static_cast ((end.tv_nsec-start.tv_nsec)/1000); + diff.tv_sec = end.tv_sec - start.tv_sec; + diff.tv_usec = static_cast ((end.tv_nsec - start.tv_nsec) / 1000); // Update the timeout if (timeout.tv_sec <= diff.tv_sec) { timeout.tv_sec = 0; @@ -434,7 +414,7 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size) #endif // Figure out what happened by looking at select's response 'r' -/** Error **/ + /** Error **/ if (r < 0) { // Select was interrupted, try again if (errno == EINTR) { @@ -443,22 +423,21 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size) // Otherwise there was some error THROW (IOException, errno); } -/** Timeout **/ + /** Timeout **/ if (r == 0) { break; } -/** Something ready to read **/ + /** Something ready to read **/ if (r > 0) { // Make sure our file descriptor is in the ready to read list if (FD_ISSET (fd_, &readfds)) { // This should be non-blocking returning only what is avaialble now // Then returning so that select can block again. ssize_t bytes_read_now = - ::read (fd_, buf+bytes_read, size-bytes_read); + ::read (fd_, buf + bytes_read, size - bytes_read); // read should always return some data as select reported it was // ready to read when we get to this point. - if (bytes_read_now < 1) - { + if (bytes_read_now < 1) { // Disconnected devices, at least on Linux, show the // behavior that they are always ready to read immediately // but reading returns nothing. @@ -484,7 +463,7 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size) } // This shouldn't happen, if r > 0 our fd has to be in the list! THROW (IOException, "select reports ready to read, but our fd isn't" - " in the list, this shouldn't happen!"); + " in the list, this shouldn't happen!"); } } return bytes_read; @@ -493,11 +472,9 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size) size_t Serial::SerialImpl::write (const string &data) { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::write"); } - return static_cast (::write (fd_, data.c_str (), data.length ())); } @@ -514,12 +491,12 @@ Serial::SerialImpl::getPort () const } void -Serial::SerialImpl::setTimeout (long timeout) +Serial::SerialImpl::setTimeout (serial::timeout_t &timeout) { timeout_ = timeout; } -long +serial::timeout_t Serial::SerialImpl::getTimeout () const { return timeout_; @@ -598,8 +575,7 @@ Serial::SerialImpl::getFlowcontrol () const void Serial::SerialImpl::flush () { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::flush"); } tcdrain (fd_); @@ -608,8 +584,7 @@ Serial::SerialImpl::flush () void Serial::SerialImpl::flushInput () { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::flushInput"); } tcflush (fd_, TCIFLUSH); @@ -618,8 +593,7 @@ Serial::SerialImpl::flushInput () void Serial::SerialImpl::flushOutput () { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::flushOutput"); } tcflush (fd_, TCOFLUSH); @@ -628,25 +602,21 @@ Serial::SerialImpl::flushOutput () void Serial::SerialImpl::sendBreak (int duration) { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::sendBreak"); } - tcsendbreak (fd_, static_cast (duration/4)); + tcsendbreak (fd_, static_cast (duration / 4)); } void Serial::SerialImpl::setBreak (bool level) { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::setBreak"); } - if (level) - { + if (level) { ioctl (fd_, TIOCSBRK); - } - else { + } else { ioctl (fd_, TIOCCBRK); } } @@ -654,15 +624,12 @@ Serial::SerialImpl::setBreak (bool level) void Serial::SerialImpl::setRTS (bool level) { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::setRTS"); } - if (level) - { + if (level) { ioctl (fd_, TIOCMBIS, TIOCM_RTS); - } - else { + } else { ioctl (fd_, TIOCMBIC, TIOCM_RTS); } } @@ -670,25 +637,45 @@ Serial::SerialImpl::setRTS (bool level) void Serial::SerialImpl::setDTR (bool level) { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::setDTR"); } - if (level) - { + if (level) { ioctl (fd_, TIOCMBIS, TIOCM_DTR); - } - else - { + } else { ioctl (fd_, TIOCMBIC, TIOCM_DTR); } } +bool +Serial::SerialImpl::waitForChange () +{ +#ifndef TIOCMIWAIT + while (is_open_ == true) { + int s = ioctl (fd_, TIOCMGET, 0); + if ((s & TIOCM_CTS) != 0) return true; + if ((s & TIOCM_DSR) != 0) return true; + if ((s & TIOCM_RI) != 0) return true; + if ((s & TIOCM_CD) != 0) return true; + usleep(1000); + } +#else + if (ioctl(fd_, TIOCMIWAIT, (TIOCM_CD|TIOCM_DSR|TIOCM_RI|TIOCM_CTS)) != 0) { + stringstream ss; + ss << "waitForDSR failed on a call to ioctl(TIOCMIWAIT): " + << errno << " " << strerror(errno); + throw(SerialExecption(ss.str().c_str())); + return false; + } + return true; +#endif + return false; +} + bool Serial::SerialImpl::getCTS () { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::getCTS"); } int s = ioctl (fd_, TIOCMGET, 0); @@ -696,10 +683,9 @@ Serial::SerialImpl::getCTS () } bool -Serial::SerialImpl::getDSR() +Serial::SerialImpl::getDSR () { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::getDSR"); } int s = ioctl (fd_, TIOCMGET, 0); @@ -709,8 +695,7 @@ Serial::SerialImpl::getDSR() bool Serial::SerialImpl::getRI() { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::getRI"); } int s = ioctl (fd_, TIOCMGET, 0); @@ -720,8 +705,7 @@ Serial::SerialImpl::getRI() bool Serial::SerialImpl::getCD() { - if (is_open_ == false) - { + if (is_open_ == false) { throw PortNotOpenedException ("Serial::getCD"); } int s = ioctl (fd_, TIOCMGET, 0); @@ -729,7 +713,8 @@ Serial::SerialImpl::getCD() } void -Serial::SerialImpl::readLock() { +Serial::SerialImpl::readLock() +{ int result = pthread_mutex_lock(&this->read_mutex); if (result) { THROW (IOException, result); @@ -737,7 +722,8 @@ Serial::SerialImpl::readLock() { } void -Serial::SerialImpl::readUnlock() { +Serial::SerialImpl::readUnlock() +{ int result = pthread_mutex_unlock(&this->read_mutex); if (result) { THROW (IOException, result); @@ -745,7 +731,8 @@ Serial::SerialImpl::readUnlock() { } void -Serial::SerialImpl::writeLock() { +Serial::SerialImpl::writeLock() +{ int result = pthread_mutex_lock(&this->write_mutex); if (result) { THROW (IOException, result); @@ -753,7 +740,8 @@ Serial::SerialImpl::writeLock() { } void -Serial::SerialImpl::writeUnlock() { +Serial::SerialImpl::writeUnlock() +{ int result = pthread_mutex_unlock(&this->write_mutex); if (result) { THROW (IOException, result); diff --git a/src/serial.cc b/src/serial.cc index 2133b06..c2e1eaa 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -48,12 +48,12 @@ private: SerialImpl *pimpl_; }; -Serial::Serial (const string &port, unsigned long baudrate, long timeout, +Serial::Serial (const string &port, unsigned long baudrate, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) : read_cache_("") { - pimpl_ = new SerialImpl (port, baudrate, timeout, bytesize, parity, + pimpl_ = new SerialImpl (port, baudrate, bytesize, parity, stopbits, flowcontrol); } @@ -230,12 +230,12 @@ Serial::getPort () const } void -Serial::setTimeout (long timeout) +Serial::setTimeout (serial::timeout_t &timeout) { pimpl_->setTimeout (timeout); } -long +serial::timeout_t Serial::getTimeout () const { return pimpl_->getTimeout (); } @@ -341,6 +341,11 @@ void Serial::setDTR (bool level) pimpl_->setDTR (level); } +bool Serial::waitForChange() +{ + return pimpl_->waitForChange(); +} + bool Serial::getCTS () { return pimpl_->getCTS (); From 194169e5e63b29a24187d758d4891b1de878ec8f Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 2 May 2012 21:49:09 -0500 Subject: [PATCH 02/16] More updates to the documentation and new api after comments from john and michael. --- include/serial/impl/unix.h | 6 ++-- include/serial/serial.h | 70 ++++++++++++++++++++++++-------------- src/impl/unix.cc | 4 +-- src/serial.cc | 7 ++-- 4 files changed, 54 insertions(+), 33 deletions(-) diff --git a/include/serial/impl/unix.h b/include/serial/impl/unix.h index 2e134df..ff8b4d1 100644 --- a/include/serial/impl/unix.h +++ b/include/serial/impl/unix.h @@ -122,9 +122,9 @@ public: getPort () const; void - setTimeout (timeout_t &timeout); + setTimeout (Timeout &timeout); - timeout_t + Timeout getTimeout () const; void @@ -180,7 +180,7 @@ private: bool xonxoff_; bool rtscts_; - timeout_t timeout_; // Timeout for read operations + Timeout timeout_; // Timeout for read operations unsigned long baudrate_; // Baudrate parity_t parity_; // Parity diff --git a/include/serial/serial.h b/include/serial/serial.h index ad29bab..3f2c60c 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include #include @@ -88,8 +88,8 @@ typedef enum { * Structure for setting the timeout of the serial port, times are * in milliseconds. */ -struct timeout_t { - timeout_t (long inter_byte_timeout_=0, long read_timeout_constant_=0, +struct Timeout { + Timeout (long inter_byte_timeout_=0, long read_timeout_constant_=0, long read_timeout_multiplier_=0, long write_timeout_constant_=0, long write_timeout_multiplier_=0) : inter_byte_timeout(inter_byte_timeout_), @@ -129,6 +129,9 @@ public: * * \param baudrate An integer that represents the baudrate * + * \param timeout A serial::Timeout struct that defines the timeout + * conditions for the serial port. \see serial::Timeout + * * \param bytesize Size of each byte in the serial transmission of data, * default is eightbits, possible values are: fivebits, sixbits, sevenbits, * eightbits @@ -147,6 +150,7 @@ public: */ Serial (const std::string &port = "", unsigned long baudrate = 9600, + Timeout timeout = Timeout(), bytesize_t bytesize = eightbits, parity_t parity = parity_none, stopbits_t stopbits = stopbits_one, @@ -341,29 +345,42 @@ public: std::string getPort () const; - /*! Sets the timeout for reads and writes using the timeout_t struct. + /*! Sets the timeout for reads and writes using the Timeout struct. * - * There are two basic conditions for timeout described here, the inter byte - * timeout is the maximum amount of time in milliseconds allowed between - * receiving bytes from the serial port. The second condition is where the - * total timeout expires during a read or write. The total timeout can be - * calculated as the multiplier times the number of requested bytes plus the - * constant. In this way a single constant time timeout can be specified - * with zero for the inter byte timeout and zero for the multiplier. - * Alternatively, you could have only an inter byte timeout and zero for - * both the constant and multiplier to prevent a total time timeout from - * occurring.You can use the multiplier to increase the total time timeout - * based on the number of bytes requested. The user can combine any of - * these timeout metrics in order to achieve the desired trade-off between - * efficiency and responsiveness. + * There are two timeout conditions described here: + * * The inter byte timeout: + * * The inter_byte_timeout component of serial::Timeout defines the + * maximum amount of time, in milliseconds, between receiving bytes on + * the serial port that can pass before a timeout occurs. Setting this + * to zero will prevent inter byte timeouts from occurring. + * * Total time timeout: + * * The the constant and multiplier component of this timeout condition, + * for both read and write, are defined in serial::Timeout. This + * timeout occurs if the total time since the read or write call was + * made exceeds the specified time in milliseconds. + * * The limit is defined by multiplying the multiplier component by the + * number of requested bytes and adding that product to the constant + * component. In this way if you want a read call, for example, to + * timeout after exactly one second regardless of the number of bytes + * you asked for then set the read_timeout_constant component of + * serial::Timeout to 1000 and the read_timeout_multiplier to zero. + * This timeout condition can be used in conjunction with the inter + * byte timeout condition with out any problems, timeout will simply + * occur when one of the two timeout conditions is met. This allows + * users to have maximum control over the trade-off between + * responsiveness and efficiency. * - * \param timeout A timeout_t struct containing the inter byte timeout, and - * the read and write timeout constants and multipliers. + * Read and write functions will return in one of three cases. When the + * reading or writing is complete, when a timeout occurs, or when an + * exception occurs. * - * \see serial::timeout_t + * \param timeout A serial::Timeout struct containing the inter byte + * timeout, and the read and write timeout constants and multipliers. + * + * \see serial::Timeout */ void - setTimeout (timeout_t &timeout); + setTimeout (Timeout &timeout); /*! Sets the timeout for reads and writes. */ void @@ -371,7 +388,7 @@ public: long read_timeout_multiplier, long write_timeout_constant, long write_timeout_multiplier) { - timeout_t timeout(inter_byte_timeout, read_timeout_constant, + Timeout timeout(inter_byte_timeout, read_timeout_constant, read_timeout_multiplier, write_timeout_constant, write_timeout_multiplier); return setTimeout(timeout); @@ -379,12 +396,12 @@ public: /*! Gets the timeout for reads in seconds. * - * \return A timeout_t struct containing the inter_byte_timeout, and read + * \return A Timeout struct containing the inter_byte_timeout, and read * and write timeout constants and multipliers. * * \see Serial::setTimeout */ - timeout_t + Timeout getTimeout () const; /*! Sets the baudrate for the serial port. @@ -520,7 +537,7 @@ public: setDTR (bool level = true); /*! - * Returns true on CTS, DSR, RI, or CD changing. + * Blocks until CTS, DSR, RI, CD changes or something interrupts it. * * Can throw an exception if an error occurs while waiting. * You can check the status of CTS, DSR, RI, and CD once this returns. @@ -528,6 +545,9 @@ public: * resolution of less than +-1ms and as good as +-0.2ms. Otherwise a * polling method is used which can give +-2ms. * + * \return Returns true if one of the lines changed, false if something else + * occurred. + * * \throw SerialException */ bool diff --git a/src/impl/unix.cc b/src/impl/unix.cc index e8d0f4c..d34d7aa 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -491,12 +491,12 @@ Serial::SerialImpl::getPort () const } void -Serial::SerialImpl::setTimeout (serial::timeout_t &timeout) +Serial::SerialImpl::setTimeout (serial::Timeout &timeout) { timeout_ = timeout; } -serial::timeout_t +serial::Timeout Serial::SerialImpl::getTimeout () const { return timeout_; diff --git a/src/serial.cc b/src/serial.cc index c2e1eaa..d391202 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -48,13 +48,14 @@ private: SerialImpl *pimpl_; }; -Serial::Serial (const string &port, unsigned long baudrate, +Serial::Serial (const string &port, unsigned long baudrate, Timeout timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) : read_cache_("") { pimpl_ = new SerialImpl (port, baudrate, bytesize, parity, stopbits, flowcontrol); + pimpl_->setTimeout(timeout); } Serial::~Serial () @@ -230,12 +231,12 @@ Serial::getPort () const } void -Serial::setTimeout (serial::timeout_t &timeout) +Serial::setTimeout (serial::Timeout &timeout) { pimpl_->setTimeout (timeout); } -serial::timeout_t +serial::Timeout Serial::getTimeout () const { return pimpl_->getTimeout (); } From 0a66fa991d411b6d2791323d361ecfd0c0fd4cfc Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 2 May 2012 23:39:42 -0500 Subject: [PATCH 03/16] Changes to the documentation generation mechanism --- doc/Doxyfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 6b4472f..5704725 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -610,7 +610,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = include/serial include/serial/impl src src/impl +INPUT = include src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -634,7 +634,7 @@ FILE_PATTERNS = # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. -RECURSIVE = NO +RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a From ba0c648119c78f282f23b96a4d31184e4351f6a0 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Mon, 7 May 2012 13:04:34 -0500 Subject: [PATCH 04/16] Fixes #16. --- include/serial/serial.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/serial/serial.h b/include/serial/serial.h index 3f2c60c..bb310b4 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include From 3039acbab9b3f93bb7f43ef73076147e691a2a49 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Mon, 7 May 2012 13:06:28 -0500 Subject: [PATCH 05/16] Adding a convenience function for generating simple Timeouts based purely on the total time until a timeout occurs with no regard to inter byte timeout or timeout multipliers. --- include/serial/serial.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/include/serial/serial.h b/include/serial/serial.h index bb310b4..8d40342 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -99,6 +99,20 @@ struct Timeout { write_timeout_constant(write_timeout_constant_), write_timeout_multiplier(write_timeout_multiplier_) {} + + /*! + * Convenience function to generate Timeout structs using a + * single absolute timeout. + * + * \param timeout A long that defines the time in milliseconds until a + * timeout occurs after a call to read or write is made. + * + * \return Timeout struct that represents this simple timeout provided. + */ + static Timeout simpleTimeout(long timeout) { + return Timeout(0, timeout, 0, timeout, 0); + } + /*! Number of milliseconds between bytes received to timeout on. */ long inter_byte_timeout; /*! A constant number of milliseconds to wait after calling read. */ From 937e83469836dda5f7a8cd9d1173820ebc06512e Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 9 May 2012 19:51:56 -0500 Subject: [PATCH 06/16] Updating the unix implementation to support the more sophisticated timeout system. --- CMakeLists.txt | 2 +- serial.sublime-workspace | 128 +++++---------------------------------- src/impl/unix.cc | 58 +++++++++++------- 3 files changed, 51 insertions(+), 137 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfffc80..d6f9e6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.4.6) set(ROS_ROOT $ENV{ROS_ROOT}) -option(SERIAL_BUILD_WIHOUT_ROS "Build without ROS?" OFF) +option(SERIAL_BUILD_WIHOUT_ROS "Build without ROS?" ON) if(DEFINED ROS_ROOT AND NOT SERIAL_BUILD_WIHOUT_ROS) # Build with ROS diff --git a/serial.sublime-workspace b/serial.sublime-workspace index 486d099..053d890 100644 --- a/serial.sublime-workspace +++ b/serial.sublime-workspace @@ -275,32 +275,8 @@ }, "buffers": [ - { - "file": "include/serial/serial.h", - "settings": - { - "buffer_size": 17876, - "line_ending": "Unix" - } - }, - { - "file": "src/serial.cc", - "settings": - { - "buffer_size": 7015, - "line_ending": "Unix" - } - }, - { - "file": "src/impl/unix.cc", - "settings": - { - "buffer_size": 16696, - "line_ending": "Unix" - } - } ], - "build_system": "Packages/Python/Python.sublime-build", + "build_system": "Packages/Makefile/Make.sublime-build", "command_palette": { "height": 47.0, @@ -332,6 +308,14 @@ }, "file_history": [ + "/Users/william/devel/serial/src/serial.cc", + "/Users/william/devel/serial/src/impl/unix.cc", + "/Users/william/devel/serial/include/serial/serial.h", + "/Users/william/devel/serial/CMakeLists.txt", + "/Users/william/devel/serial/serial.sublime-project", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py", @@ -343,7 +327,6 @@ "/Users/william/devel/xbow400/src/xbow_400.cpp", "/Users/william/devel/xbow400/README", "/Users/william/devel/xbow400/xbow400.sublime-project", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", "/Users/william/devel/comp6400/homework6/homework6.sublime-project", "/Users/william/devel/comp6400/homework6/src/main.cc", "/Users/william/devel/comp6400/homework6/models/student.obj", @@ -462,95 +445,8 @@ "groups": [ { - "selected": 2, "sheets": [ - { - "buffer": 0, - "file": "include/serial/serial.h", - "settings": - { - "buffer_size": 17876, - "regions": - { - }, - "selection": - [ - [ - 11407, - 11407 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 4, - "translate_tabs_to_spaces": true, - "word_wrap": true, - "wrap_width": 80 - }, - "translation.x": 0.0, - "translation.y": 6934.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 1, - "file": "src/serial.cc", - "settings": - { - "buffer_size": 7015, - "regions": - { - }, - "selection": - [ - [ - 0, - 0 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 479.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 2, - "file": "src/impl/unix.cc", - "settings": - { - "buffer_size": 16696, - "regions": - { - }, - "selection": - [ - [ - 15521, - 15521 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 10013.0, - "zoom_level": 1.0 - }, - "type": "text" - } ] }, { @@ -587,7 +483,7 @@ "cols": [ 0.0, - 0.61784814072, + 0.766633361467, 1.0 ], "rows": @@ -601,6 +497,10 @@ { "height": 100.0 }, + "output.exec": + { + "height": 229.0 + }, "replace": { "height": 64.0 diff --git a/src/impl/unix.cc b/src/impl/unix.cc index d34d7aa..10af480 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -371,47 +371,61 @@ inline void get_time_now(struct timespec &time) size_t Serial::SerialImpl::read (unsigned char *buf, size_t size) { + // If the port is not open, throw if (!is_open_) { throw PortNotOpenedException ("Serial::read"); } fd_set readfds; size_t bytes_read = 0; - struct timeval timeout; - timeout.tv_sec = timeout_.read_timeout_constant / 1000; - timeout.tv_usec = static_cast (timeout_.read_timeout_constant % 1000); - timeout.tv_usec *= 1000; // To convert to micro seconds + // Setup the total_timeout timeval + // This timeout is maximum time before a timeout after read is called + struct timeval total_timeout; + // Calculate total timeout in milliseconds t_c + (t_m * N) + long total_timeout_ms = timeout_.read_timeout_constant; + total_timeout_ms += timeout_.read_timeout_multiplier*static_cast(size); + total_timeout.tv_sec = total_timeout_ms / 1000; + total_timeout.tv_usec = static_cast(total_timeout_ms % 1000); + total_timeout.tv_usec *= 1000; // To convert to micro seconds while (bytes_read < size) { + // Setup the inter_byte timeout timeval + struct timeval timeout; // Inter-byte timeout + timeout.tv_sec = timeout_.inter_byte_timeout / 1000; + timeout.tv_usec = static_cast (timeout_.inter_byte_timeout % 1000); + timeout.tv_usec *= 1000; // To convert to micro seconds FD_ZERO (&readfds); FD_SET (fd_, &readfds); - // On Linux the timeout struct is updated by select to contain the time - // left on the timeout to make looping easier, but on other platforms this - // does not occur. -#if !defined(__linux__) // Begin timing select struct timespec start, end; - get_time_now(start); -#endif - // Do the select - int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); -#if !defined(__linux__) + get_time_now (start); + int r; + // If the total_timeout is less than the inter_byte_timeout + if (total_timeout.tv_sec < timeout.tv_sec + || (total_timeout.tv_sec == timeout.tv_sec + && total_timeout.tv_usec < timeout.tv_sec)) + { + // Use the total_timeout + r = select (fd_ + 1, &readfds, NULL, NULL, &total_timeout); + } else { + // Else use the inter_byte_timeout + r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); + } // Calculate difference and update the structure - get_time_now(end); + get_time_now (end); // Calculate the time select took struct timeval diff; diff.tv_sec = end.tv_sec - start.tv_sec; diff.tv_usec = static_cast ((end.tv_nsec - start.tv_nsec) / 1000); // Update the timeout - if (timeout.tv_sec <= diff.tv_sec) { - timeout.tv_sec = 0; + if (total_timeout.tv_sec <= diff.tv_sec) { + total_timeout.tv_sec = 0; } else { - timeout.tv_sec -= diff.tv_sec; + total_timeout.tv_sec -= diff.tv_sec; } - if (timeout.tv_usec <= diff.tv_usec) { - timeout.tv_usec = 0; + if (total_timeout.tv_usec <= diff.tv_usec) { + total_timeout.tv_usec = 0; } else { - timeout.tv_usec -= diff.tv_usec; + total_timeout.tv_usec -= diff.tv_usec; } -#endif // Figure out what happened by looking at select's response 'r' /** Error **/ @@ -431,7 +445,7 @@ Serial::SerialImpl::read (unsigned char *buf, size_t size) if (r > 0) { // Make sure our file descriptor is in the ready to read list if (FD_ISSET (fd_, &readfds)) { - // This should be non-blocking returning only what is avaialble now + // This should be non-blocking returning only what is available now // Then returning so that select can block again. ssize_t bytes_read_now = ::read (fd_, buf + bytes_read, size - bytes_read); From 15f01a53a12bcb9d5266dcf3feed360204954628 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 10 May 2012 11:43:17 -0500 Subject: [PATCH 07/16] Adjustments to the read timeouts --- .gitignore | 1 + serial.sublime-project | 2 + serial.sublime-workspace | 531 --------------------------------------- src/impl/unix.cc | 38 +-- 4 files changed, 24 insertions(+), 548 deletions(-) delete mode 100644 serial.sublime-workspace diff --git a/.gitignore b/.gitignore index 00f5a05..2fa13ef 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ patched wiped msg_gen srv_gen +*sublime-workspace diff --git a/serial.sublime-project b/serial.sublime-project index 1746fa9..c6270a1 100644 --- a/serial.sublime-project +++ b/serial.sublime-project @@ -1,4 +1,6 @@ { + "word_wrap": "on", + "wrap_width": 80, "folders": [ { diff --git a/serial.sublime-workspace b/serial.sublime-workspace deleted file mode 100644 index 053d890..0000000 --- a/serial.sublime-workspace +++ /dev/null @@ -1,531 +0,0 @@ -{ - "auto_complete": - { - "selected_items": - [ - [ - "tour", - "toupper(int _c) int" - ], - [ - "rotat", - "SceneObject::rotateTo(GLfloat roll, GLfloat pitch, GLfloat yaw) void" - ], - [ - "tou", - "touring_index size_t" - ], - [ - "person", - "person_mbb Model::CollisionBox" - ], - [ - "SE", - "SE Model::CollisionBox" - ], - [ - "m", - "mbb Model::CollisionBox" - ], - [ - "glVer", - "glVertex2fv(const GLfloat *v) void" - ], - [ - "di", - "distance GLfloat" - ], - [ - "the", - "their_position GLfloat *" - ], - [ - "their", - "their_obj_it vector::iterator" - ], - [ - "my", - "my_obj_it vector::iterator" - ], - [ - "my_mod", - "my_model_it vector::iterator" - ], - [ - "thei", - "their_model_it vector::iterator" - ], - [ - "iterator", - "assign(_InputIterator __first, _InputIterator __last) void" - ], - [ - "get", - "getPosition() GLfloat *" - ], - [ - "lh", - "lhs_mbb Model::CollisionBox" - ], - [ - "cal", - "calculateMBB(Model::Object &obj) Model::CollisionBox" - ], - [ - "Col", - "CollisionBox " - ], - [ - "spo", - "spotlight LightingStyle" - ], - [ - "main", - "main_camera Camera" - ], - [ - "pers", - "person Person *" - ], - [ - "glro", - "glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "glTran", - "glTranslatef(GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "she", - "shelby_model string" - ], - [ - "loa", - "loaded_ bool" - ], - [ - "ena", - "enabled_ bool" - ], - [ - "sp", - "specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a) void" - ], - [ - "en", - "direction(GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "spot", - "spot_light Light" - ], - [ - "GL_NOR", - "GL_NORMALIZE " - ], - [ - "att", - "attenuation_q_ GLfloat" - ], - [ - "atte", - "attenuation_c_ GLfloat" - ], - [ - "glPop", - "glPopMatrix() void" - ], - [ - "appl", - "apply_() void" - ], - [ - "no_l", - "no_lights_left const size_t" - ], - [ - "ligh", - "lights_left size_t" - ], - [ - "do", - "do_normals bool" - ], - [ - "back_in", - "back_inserter(_Container &__x) back_insert_iterator<_Container>" - ], - [ - "istr", - "istream_iterator " - ], - [ - "is", - "istringstream " - ], - [ - "math", - "matches size_t" - ], - [ - "curr", - "current_object Model::Object" - ], - [ - "matc", - "matches2 size_t" - ], - [ - "QwtPlot", - "QwtPlotZoomer" - ], - [ - "__init", - "__initZooming" - ], - [ - "plot_coi", - "plot_coil2" - ], - [ - "plo", - "plot_coil1" - ], - [ - "plot_co", - "plot_coil2" - ], - [ - "QwtPl", - "QwtPlotCurve" - ], - [ - "trail", - "trailer_plotcurve" - ], - [ - "pl", - "plot_coil1" - ], - [ - "plot", - "plot_coil1" - ], - [ - "open", - "open_button" - ], - [ - "plotcoi", - "plot_coil1" - ], - [ - "EM", - "EM61MK2Log" - ], - [ - "pa", - "path_file_name" - ], - [ - "head", - "headings" - ], - [ - "eas", - "eastings" - ], - [ - "north", - "northings" - ], - [ - "las", - "last_east" - ], - [ - "odom", - "odom" - ], - [ - "logs", - "logs_data" - ], - [ - "plot_", - "plot_em61mk2logs" - ], - [ - "Em61", - "EM61MK2Log" - ], - [ - "sib", - "sibling_file_name" - ], - [ - "si", - "sibling_file_name" - ], - [ - "fil", - "file_name" - ] - ] - }, - "buffers": - [ - ], - "build_system": "Packages/Makefile/Make.sublime-build", - "command_palette": - { - "height": 47.0, - "selected_items": - [ - [ - "install", - "Package Control: Install Package" - ], - [ - "late", - "LaTeXTools: View PDF" - ] - ], - "width": 449.0 - }, - "console": - { - "height": 0.0 - }, - "distraction_free": - { - "menu_visible": true, - "show_minimap": false, - "show_open_files": false, - "show_tabs": false, - "side_bar_visible": false, - "status_bar_visible": false - }, - "file_history": - [ - "/Users/william/devel/serial/src/serial.cc", - "/Users/william/devel/serial/src/impl/unix.cc", - "/Users/william/devel/serial/include/serial/serial.h", - "/Users/william/devel/serial/CMakeLists.txt", - "/Users/william/devel/serial/serial.sublime-project", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/survey.csv", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/image_generator.py", - "/Users/william/.ros/rosdep.yaml", - "/Users/william/.bashrc", - "/Users/william/devel/xbow400/include/xbow_400.h", - "/Users/william/devel/xbow400/src/xbow_400.cpp", - "/Users/william/devel/xbow400/README", - "/Users/william/devel/xbow400/xbow400.sublime-project", - "/Users/william/devel/comp6400/homework6/homework6.sublime-project", - "/Users/william/devel/comp6400/homework6/src/main.cc", - "/Users/william/devel/comp6400/homework6/models/student.obj", - "/Users/william/devel/comp6400/homework6/models/ground.obj", - "/Users/william/devel/comp6400/homework6/models/shelby.obj", - "/Users/william/devel/comp6400/homework6/models/ground.mtl", - "/Users/william/devel/comp6400/homework6/models/shelby.mtl", - "/Users/william/devel/comp6400/homework6/CMakeLists.txt", - "/Users/william/devel/comp6400/homework6/models/shelby.blend", - "/Users/william/devel/comp6400/homework6/Makefile", - "/usr/include/c++/4.2.1/tr1/cstdio", - "/Users/william/devel/comp6400/homework6/src/michaels.cc", - "/Users/william/devel/auxos_orig/scripts/plot_em.py", - "/Users/william/devel/auxos_orig/scripts/logtool.py", - "/Users/william/devel/auxos_orig/scripts/em61mk2.py", - "/Users/william/devel/auxos_orig/scripts/lib/__init__.py", - "/usr/local/Library/Formula/pyqt.rb", - "/usr/local/Library/Formula/pyqwt.rb", - "/Users/william/devel/3dteleop_ws/3d_teleop/redo_slam_offline/launch/play_and_remap_tf.launch", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/launch/automow_stuff.launch", - "/Users/william/devel/auxos_orig/scripts/coords2path.py", - "/Users/william/Downloads/sup1_waypts_utm_path.txt", - "/Users/william/Downloads/example.txt", - "/Users/william/devel/auxos_orig/scripts/sup1_waypts_utm_path.txt", - "/Users/william/devel/ion_plans_paper/citations.bib", - "/Users/william/devel/ion_plans_paper/ion_plans.tex", - "/Users/william/Desktop/em61mk2.py", - "/Users/william/devel/ion_plans_paper/ion_plans.log", - "/Users/william/devel/ion_plans_paper/ion_plans.pdf", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OcTree.h", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.h", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.hxx", - "/Users/william/devel/3dteleop_ws/octomap/octomap/src/OcTree.cpp", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/octomap_deprecated.h", - "/Users/william/devel/3dteleop_ws/octomap/CMakeLists.txt", - "/Users/william/devel/comp6400/homework3/src/main.cc", - "/Users/william/Desktop/untitled.obj", - "/Users/william/devel/cs373-tests/util.py", - "/Users/william/devel/cs373-tests/2.6/code.py", - "/Users/william/devel/cs373-tests/2.6/template.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/manifest.xml", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/odom2tf.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/automow_laser_filter.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/rename_tf_frame.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/remap_tf.py", - "/Users/william/Downloads/orocos_kinematics_dynamics-ffdeaad-install_name_tool.patch", - "/Users/william/devel/automow_ws/au_automow_common/automow_bringup/launch/minimal.launch", - "/Users/william/devel/vis_ws/visualization/rviz/manifest.xml", - "/Library/Python/2.7/site-packages/pkg_resources.py", - "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", - "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/plot_em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/plot_em61mk2.py" - ], - "find": - { - "height": 35.0 - }, - "find_in_files": - { - "height": 0.0, - "where_history": - [ - "" - ] - }, - "find_state": - { - "case_sensitive": false, - "find_history": - [ - "cts", - " ", - "o ", - "Cube_Cube.001", - "min[2]", - "min[1]", - "max[2]", - "max[1]", - "max[0]", - "min[0]", - "window_width", - "800", - "•", - "Cube", - "expected 1.", - "counter", - "go", - "setZoomerMousePattern", - "updateNode", - "compute", - "insertS" - ], - "highlight": true, - "in_selection": false, - "preserve_case": false, - "regex": false, - "replace_history": - [ - ", ", - "min.z", - "min.y", - "max.z", - "max.y", - "max.x", - "min.x", - "*" - ], - "reverse": false, - "show_context": true, - "use_buffer2": true, - "whole_word": false, - "wrap": true - }, - "groups": - [ - { - "sheets": - [ - ] - }, - { - "sheets": - [ - ] - } - ], - "incremental_find": - { - "height": 0.0 - }, - "input": - { - "height": 31.0 - }, - "layout": - { - "cells": - [ - [ - 0, - 0, - 1, - 1 - ], - [ - 1, - 0, - 2, - 1 - ] - ], - "cols": - [ - 0.0, - 0.766633361467, - 1.0 - ], - "rows": - [ - 0.0, - 1.0 - ] - }, - "menu_visible": true, - "output.clang": - { - "height": 100.0 - }, - "output.exec": - { - "height": 229.0 - }, - "replace": - { - "height": 64.0 - }, - "save_all_on_build": true, - "select_file": - { - "height": 0.0, - "selected_items": - [ - ], - "width": 0.0 - }, - "select_project": - { - "height": 0.0, - "selected_items": - [ - ], - "width": 0.0 - }, - "show_minimap": false, - "show_open_files": false, - "show_tabs": true, - "side_bar_visible": true, - "side_bar_width": 283.0, - "status_bar_visible": true -} diff --git a/src/impl/unix.cc b/src/impl/unix.cc index 10af480..9064ef2 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -386,29 +386,33 @@ Serial::SerialImpl::read (unsigned char *buf, size_t size) total_timeout.tv_sec = total_timeout_ms / 1000; total_timeout.tv_usec = static_cast(total_timeout_ms % 1000); total_timeout.tv_usec *= 1000; // To convert to micro seconds + // Setup the inter byte timeout + struct timeval inter_byte_timeout; + inter_byte_timeout.tv_sec = timeout_.inter_byte_timeout / 1000; + inter_byte_timeout.tv_usec = + static_cast (timeout_.inter_byte_timeout % 1000); + inter_byte_timeout.tv_usec *= 1000; // To convert to micro seconds while (bytes_read < size) { - // Setup the inter_byte timeout timeval - struct timeval timeout; // Inter-byte timeout - timeout.tv_sec = timeout_.inter_byte_timeout / 1000; - timeout.tv_usec = static_cast (timeout_.inter_byte_timeout % 1000); - timeout.tv_usec *= 1000; // To convert to micro seconds + // Setup the select timeout timeval + struct timeval timeout; + // If the total_timeout is less than the inter_byte_timeout + if (total_timeout.tv_sec < inter_byte_timeout.tv_sec + || (total_timeout.tv_sec == inter_byte_timeout.tv_sec + && total_timeout.tv_usec < inter_byte_timeout.tv_sec)) + { + // Then set the select timeout to use the total time + timeout = total_timeout; + } else { + // Else set the select timeout to use the inter byte time + timeout = inter_byte_timeout; + } FD_ZERO (&readfds); FD_SET (fd_, &readfds); // Begin timing select struct timespec start, end; get_time_now (start); - int r; - // If the total_timeout is less than the inter_byte_timeout - if (total_timeout.tv_sec < timeout.tv_sec - || (total_timeout.tv_sec == timeout.tv_sec - && total_timeout.tv_usec < timeout.tv_sec)) - { - // Use the total_timeout - r = select (fd_ + 1, &readfds, NULL, NULL, &total_timeout); - } else { - // Else use the inter_byte_timeout - r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); - } + // Call select to block for serial data or a timeout + int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); // Calculate difference and update the structure get_time_now (end); // Calculate the time select took From dcc73db6a82d90cfc886c99ca0d82086081460a8 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Fri, 11 May 2012 15:28:23 -0500 Subject: [PATCH 08/16] Syntax fix --- src/impl/unix.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/impl/unix.cc b/src/impl/unix.cc index 9064ef2..6705bf3 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -711,7 +711,7 @@ Serial::SerialImpl::getDSR () } bool -Serial::SerialImpl::getRI() +Serial::SerialImpl::getRI () { if (is_open_ == false) { throw PortNotOpenedException ("Serial::getRI"); @@ -721,7 +721,7 @@ Serial::SerialImpl::getRI() } bool -Serial::SerialImpl::getCD() +Serial::SerialImpl::getCD () { if (is_open_ == false) { throw PortNotOpenedException ("Serial::getCD"); @@ -731,7 +731,7 @@ Serial::SerialImpl::getCD() } void -Serial::SerialImpl::readLock() +Serial::SerialImpl::readLock () { int result = pthread_mutex_lock(&this->read_mutex); if (result) { @@ -740,7 +740,7 @@ Serial::SerialImpl::readLock() } void -Serial::SerialImpl::readUnlock() +Serial::SerialImpl::readUnlock () { int result = pthread_mutex_unlock(&this->read_mutex); if (result) { @@ -749,7 +749,7 @@ Serial::SerialImpl::readUnlock() } void -Serial::SerialImpl::writeLock() +Serial::SerialImpl::writeLock () { int result = pthread_mutex_lock(&this->write_mutex); if (result) { @@ -758,7 +758,7 @@ Serial::SerialImpl::writeLock() } void -Serial::SerialImpl::writeUnlock() +Serial::SerialImpl::writeUnlock () { int result = pthread_mutex_unlock(&this->write_mutex); if (result) { From 6fac95d633e3731555f8d228da3140370bab0433 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 6 Jun 2012 18:56:44 -0500 Subject: [PATCH 09/16] Adding initial windows support. --- .gitignore | 1 + Findserial.cmake | 4 +- README.md | 2 +- include/serial/impl/unix.h | 6 +- include/serial/impl/{windows.h => win.h} | 73 ++- include/serial/serial.h | 53 +- serial.sublime-workspace | 204 +++---- src/impl/unix.cc | 98 +++- src/impl/win.cc | 549 +++++++++++++++++++ src/impl/windows.cc | 670 ----------------------- src/serial.cc | 49 +- 11 files changed, 847 insertions(+), 862 deletions(-) rename include/serial/impl/{windows.h => win.h} (81%) create mode 100644 src/impl/win.cc delete mode 100644 src/impl/windows.cc diff --git a/.gitignore b/.gitignore index 00f5a05..b13b41e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ patched wiped msg_gen srv_gen +doc/html diff --git a/Findserial.cmake b/Findserial.cmake index 6d27e7e..20fccd0 100644 --- a/Findserial.cmake +++ b/Findserial.cmake @@ -1,5 +1,5 @@ -find_path(serial_INCLUDE_DIRS serial.h /usr/include/serial - /usr/local/include/serial "$ENV{NAMER_ROOT}") +find_path(serial_INCLUDE_DIRS serial/serial.h /usr/include + /usr/local/include "$ENV{NAMER_ROOT}") find_library(serial_LIBRARIES serial /usr/lib /usr/local/lib "$ENV{NAMER_ROOT}") diff --git a/README.md b/README.md index 31297de..9829480 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Run the example: The BSD License -Copyright (c) 2011 William Woodall +Copyright (c) 2012 William Woodall Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/include/serial/impl/unix.h b/include/serial/impl/unix.h index ff8b4d1..6700a24 100644 --- a/include/serial/impl/unix.h +++ b/include/serial/impl/unix.h @@ -8,7 +8,7 @@ * * The MIT License * - * Copyright (c) 2011 William Woodall, John Harrison + * Copyright (c) 2012 William Woodall, John Harrison * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -74,10 +74,10 @@ public: available (); size_t - read (unsigned char *buf, size_t size = 1); + read (uint8_t *buf, size_t size = 1); size_t - write (const string &data); + write (const uint8_t *data, size_t length); void flush (); diff --git a/include/serial/impl/windows.h b/include/serial/impl/win.h similarity index 81% rename from include/serial/impl/windows.h rename to include/serial/impl/win.h index aa06706..902a70a 100644 --- a/include/serial/impl/windows.h +++ b/include/serial/impl/win.h @@ -8,7 +8,7 @@ * * The MIT License * - * Copyright (c) 2011 William Woodall, John Harrison + * Copyright (c) 2012 William Woodall, John Harrison * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -39,6 +39,8 @@ #include "serial/serial.h" +#include "windows.h" + namespace serial { using std::string; @@ -51,7 +53,6 @@ class serial::Serial::SerialImpl { public: SerialImpl (const string &port, unsigned long baudrate, - long timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, @@ -72,10 +73,10 @@ public: available (); size_t - read (char* buf, size_t size = 1); + read (uint8_t *buf, size_t size = 1); size_t - write (const string &data); + write (const uint8_t *data, size_t length); void flush (); @@ -87,50 +88,53 @@ public: flushOutput (); void - sendBreak(int duration); + sendBreak (int duration); void - setBreak(bool level); + setBreak (bool level); void - setRTS(bool level); + setRTS (bool level); void - setDTR(bool level); - + setDTR (bool level); + bool - getCTS(); - + waitForChange (); + bool - getDSR(); - + getCTS (); + bool - getRI(); - + getDSR (); + bool - getCD(); + getRI (); + + bool + getCD (); void setPort (const string &port); - + string getPort () const; void - setTimeout (long timeout); - - long + setTimeout (Timeout &timeout); + + Timeout getTimeout () const; void setBaudrate (unsigned long baudrate); - + unsigned long getBaudrate () const; void setBytesize (bytesize_t bytesize); - + bytesize_t getBytesize () const; @@ -152,24 +156,39 @@ public: flowcontrol_t getFlowcontrol () const; + void + readLock (); + + void + readUnlock (); + + void + writeLock (); + + void + writeUnlock (); + protected: void reconfigurePort (); private: string port_; // Path to the file descriptor - int fd_; // The current file descriptor + HANDLE fd_; - bool isOpen_; - bool xonxoff_; - bool rtscts_; + bool is_open_; - long timeout_; // Timeout for read operations + Timeout timeout_; // Timeout for read operations unsigned long baudrate_; // Baudrate parity_t parity_; // Parity bytesize_t bytesize_; // Size of the bytes stopbits_t stopbits_; // Stop Bits flowcontrol_t flowcontrol_; // Flow Control + + // Mutex used to lock the read functions + HANDLE read_mutex; + // Mutex used to lock the write functions + HANDLE write_mutex; }; } diff --git a/include/serial/serial.h b/include/serial/serial.h index 3f2c60c..84970d2 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -8,7 +8,7 @@ * * The MIT License * - * Copyright (c) 2011 William Woodall + * Copyright (c) 2012 William Woodall * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -42,6 +42,7 @@ #include #include #include +#include #define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ __LINE__, (message) ) @@ -89,9 +90,9 @@ typedef enum { * in milliseconds. */ struct Timeout { - Timeout (long inter_byte_timeout_=0, long read_timeout_constant_=0, - long read_timeout_multiplier_=0, long write_timeout_constant_=0, - long write_timeout_multiplier_=0) + Timeout (int32_t inter_byte_timeout_=0, int32_t read_timeout_constant_=0, + int32_t read_timeout_multiplier_=0, int32_t write_timeout_constant_=0, + int32_t write_timeout_multiplier_=0) : inter_byte_timeout(inter_byte_timeout_), read_timeout_constant(read_timeout_constant_), read_timeout_multiplier(read_timeout_multiplier_), @@ -99,19 +100,19 @@ struct Timeout { write_timeout_multiplier(write_timeout_multiplier_) {} /*! Number of milliseconds between bytes received to timeout on. */ - long inter_byte_timeout; + int32_t inter_byte_timeout; /*! A constant number of milliseconds to wait after calling read. */ - long read_timeout_constant; + int32_t read_timeout_constant; /*! A multiplier against the number of requested bytes to wait after * calling read. */ - long read_timeout_multiplier; + int32_t read_timeout_multiplier; /*! A constant number of milliseconds to wait after calling write. */ - long write_timeout_constant; + int32_t write_timeout_constant; /*! A multiplier against the number of requested bytes to wait after * calling write. */ - long write_timeout_multiplier; + int32_t write_timeout_multiplier; }; /*! @@ -149,7 +150,7 @@ public: * \throw PortNotOpenedException */ Serial (const std::string &port = "", - unsigned long baudrate = 9600, + uint32_t baudrate = 9600, Timeout timeout = Timeout(), bytesize_t bytesize = eightbits, parity_t parity = parity_none, @@ -209,25 +210,25 @@ public: * occur. * * An exception occurred, in this case an actual exception will be thrown. * - * \param buffer An unsigned char array of at least the requested size. + * \param buffer An uint8_t array of at least the requested size. * \param size A size_t defining how many bytes to be read. * * \return A size_t representing the number of bytes read as a result of the * call to read. */ size_t - read (unsigned char *buffer, size_t size); + read (uint8_t *buffer, size_t size); /*! Read a given amount of bytes from the serial port into a give buffer. * - * \param buffer A reference to a std::vector of unsigned char. + * \param buffer A reference to a std::vector of uint8_t. * \param size A size_t defining how many bytes to be read. * * \return A size_t representing the number of bytes read as a result of the * call to read. */ size_t - read (std::vector &buffer, size_t size = 1); + read (std::vector &buffer, size_t size = 1); /*! Read a given amount of bytes from the serial port into a give buffer. * @@ -301,7 +302,7 @@ public: * the serial port. */ size_t - write (const unsigned char *data, size_t size); + write (const uint8_t *data, size_t size); /*! Write a string to the serial port. * @@ -312,7 +313,7 @@ public: * the serial port. */ size_t - write (const std::vector &data); + write (const std::vector &data); /*! Write a string to the serial port. * @@ -384,9 +385,9 @@ public: /*! Sets the timeout for reads and writes. */ void - setTimeout (long inter_byte_timeout, long read_timeout_constant, - long read_timeout_multiplier, long write_timeout_constant, - long write_timeout_multiplier) + setTimeout (int32_t inter_byte_timeout, int32_t read_timeout_constant, + int32_t read_timeout_multiplier, int32_t write_timeout_constant, + int32_t write_timeout_multiplier) { Timeout timeout(inter_byte_timeout, read_timeout_constant, read_timeout_multiplier, write_timeout_constant, @@ -417,7 +418,7 @@ public: * \throw InvalidConfigurationException */ void - setBaudrate (unsigned long baudrate); + setBaudrate (uint32_t baudrate); /*! Gets the baudrate for the serial port. * @@ -427,7 +428,7 @@ public: * * \throw InvalidConfigurationException */ - unsigned long + uint32_t getBaudrate () const; /*! Sets the bytesize for the serial port. @@ -587,7 +588,10 @@ private: // Read common function size_t - read_ (unsigned char *buffer, size_t size); + read_ (uint8_t *buffer, size_t size); + // Write common function + size_t + write_ (const uint8_t *data, size_t length); }; @@ -646,11 +650,6 @@ public: } }; -class SerialExceptionBase : public std::exception -{ - -}; - } // namespace serial #endif diff --git a/serial.sublime-workspace b/serial.sublime-workspace index 486d099..9fa9b00 100644 --- a/serial.sublime-workspace +++ b/serial.sublime-workspace @@ -3,6 +3,46 @@ { "selected_items": [ + [ + "baudr", + "baudrate_" + ], + [ + "dcb", + "dcbSerialParams" + ], + [ + "byte", + "bytes_written size_t" + ], + [ + "write", + "write_timeout_multiplier int32_t" + ], + [ + "read", + "read_timeout_multiplier" + ], + [ + "read_", + "read_timeout_multiplier" + ], + [ + "inter", + "inter_byte_timeout" + ], + [ + "write_", + "write_timeout_constant" + ], + [ + "string", + "stringstream" + ], + [ + "Seri", + "SerialExecption" + ], [ "tour", "toupper(int _c) int" @@ -275,41 +315,25 @@ }, "buffers": [ - { - "file": "include/serial/serial.h", - "settings": - { - "buffer_size": 17876, - "line_ending": "Unix" - } - }, - { - "file": "src/serial.cc", - "settings": - { - "buffer_size": 7015, - "line_ending": "Unix" - } - }, - { - "file": "src/impl/unix.cc", - "settings": - { - "buffer_size": 16696, - "line_ending": "Unix" - } - } ], "build_system": "Packages/Python/Python.sublime-build", "command_palette": { - "height": 47.0, + "height": 87.0, "selected_items": [ + [ + "convert sp", + "Indentation: Convert to Spaces" + ], [ "install", "Package Control: Install Package" ], + [ + "Package Control: remo", + "Package Control: Remove Package" + ], [ "late", "LaTeXTools: View PDF" @@ -332,6 +356,27 @@ }, "file_history": [ + "/Users/william/devel/serial/include/serial/serial.h", + "/Users/william/devel/serial/include/serial/impl/win.h", + "/Users/william/devel/serial/src/impl/win.cc", + "/Users/william/devel/serial/src/impl/unix.cc", + "/Users/william/devel/serial/include/serial/impl/unix.h", + "/Users/william/devel/serial/src/serial.cc", + "/Users/william/devel/serial/Findserial.cmake", + "/Users/william/devel/serial/src/impl/windows.cc", + "/Users/william/devel/serial/serial.sublime-project", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings", + "/Users/william/devel/serial/README.md", + "/Users/william/devel/serial/doc/html/serial_8h.html", + "/Users/william/devel/serial/doc/html/unix_8h.html", + "/Users/william/devel/serial/doc/html/windows_8h.html", + "/Users/william/devel/serial/include/serial/impl/windows.h", + "/Users/william/devel/serial/doc/Doxyfile", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/Terminal/Default (OSX).sublime-keymap", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/SublimeAStyleFormatter.sublime-settings", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap", + "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/Default (OSX).sublime-keymap", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py", @@ -343,7 +388,6 @@ "/Users/william/devel/xbow400/src/xbow_400.cpp", "/Users/william/devel/xbow400/README", "/Users/william/devel/xbow400/xbow400.sublime-project", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", "/Users/william/devel/comp6400/homework6/homework6.sublime-project", "/Users/william/devel/comp6400/homework6/src/main.cc", "/Users/william/devel/comp6400/homework6/models/student.obj", @@ -405,9 +449,10 @@ }, "find_in_files": { - "height": 0.0, + "height": 93.0, "where_history": [ + "", "" ] }, @@ -416,6 +461,18 @@ "case_sensitive": false, "find_history": [ + "flowcon", + "xonxoff_", + "rtscts_", + "#ifdef B", + "baud = B", + "write", + "char", + "unsigned char", + "char", + "long", + "2011", + " *", "cts", " ", "o ", @@ -444,6 +501,10 @@ "regex": false, "replace_history": [ + "#ifdef CBR_", + "dcbSerialParams.BaudRate = CBR_", + "2012", + " *", ", ", "min.z", "min.y", @@ -462,95 +523,8 @@ "groups": [ { - "selected": 2, "sheets": [ - { - "buffer": 0, - "file": "include/serial/serial.h", - "settings": - { - "buffer_size": 17876, - "regions": - { - }, - "selection": - [ - [ - 11407, - 11407 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 4, - "translate_tabs_to_spaces": true, - "word_wrap": true, - "wrap_width": 80 - }, - "translation.x": 0.0, - "translation.y": 6934.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 1, - "file": "src/serial.cc", - "settings": - { - "buffer_size": 7015, - "regions": - { - }, - "selection": - [ - [ - 0, - 0 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 479.0, - "zoom_level": 1.0 - }, - "type": "text" - }, - { - "buffer": 2, - "file": "src/impl/unix.cc", - "settings": - { - "buffer_size": 16696, - "regions": - { - }, - "selection": - [ - [ - 15521, - 15521 - ] - ], - "settings": - { - "syntax": "Packages/C++/C++.tmLanguage", - "tab_size": 2, - "translate_tabs_to_spaces": true - }, - "translation.x": 0.0, - "translation.y": 10013.0, - "zoom_level": 1.0 - }, - "type": "text" - } ] }, { @@ -587,7 +561,7 @@ "cols": [ 0.0, - 0.61784814072, + 0.71805886817, 1.0 ], "rows": diff --git a/src/impl/unix.cc b/src/impl/unix.cc index d34d7aa..d39cc01 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -369,7 +369,7 @@ inline void get_time_now(struct timespec &time) } size_t -Serial::SerialImpl::read (unsigned char *buf, size_t size) +Serial::SerialImpl::read (uint8_t *buf, size_t size) { if (!is_open_) { throw PortNotOpenedException ("Serial::read"); @@ -470,12 +470,104 @@ Serial::SerialImpl::read (unsigned char *buf, size_t size) } size_t -Serial::SerialImpl::write (const string &data) +Serial::SerialImpl::write (const uint8_t *data, size_t length) { if (is_open_ == false) { throw PortNotOpenedException ("Serial::write"); } - return static_cast (::write (fd_, data.c_str (), data.length ())); + fd_set writefds; + size_t bytes_written = 0; + struct timeval timeout; + timeout.tv_sec = timeout_.write_timeout_constant / 1000; + timeout.tv_usec = static_cast (timeout_.write_timeout_multiplier % 1000); + timeout.tv_usec *= 1000; // To convert to micro seconds + while (bytes_written < length) { + FD_ZERO (&writefds); + FD_SET (fd_, &writefds); + // On Linux the timeout struct is updated by select to contain the time + // left on the timeout to make looping easier, but on other platforms this + // does not occur. +#if !defined(__linux__) + // Begin timing select + struct timespec start, end; + get_time_now(start); +#endif + // Do the select + int r = select (fd_ + 1, &writefds, NULL, NULL, &timeout); +#if !defined(__linux__) + // Calculate difference and update the structure + get_time_now(end); + // Calculate the time select took + struct timeval diff; + diff.tv_sec = end.tv_sec - start.tv_sec; + diff.tv_usec = static_cast ((end.tv_nsec - start.tv_nsec) / 1000); + // Update the timeout + if (timeout.tv_sec <= diff.tv_sec) { + timeout.tv_sec = 0; + } else { + timeout.tv_sec -= diff.tv_sec; + } + if (timeout.tv_usec <= diff.tv_usec) { + timeout.tv_usec = 0; + } else { + timeout.tv_usec -= diff.tv_usec; + } +#endif + + // Figure out what happened by looking at select's response 'r' + /** Error **/ + if (r < 0) { + // Select was interrupted, try again + if (errno == EINTR) { + continue; + } + // Otherwise there was some error + THROW (IOException, errno); + } + /** Timeout **/ + if (r == 0) { + break; + } + /** Something ready to read **/ + if (r > 0) { + // Make sure our file descriptor is in the ready to read list + if (FD_ISSET (fd_, &writefds)) { + // This should be non-blocking returning only what is avaialble now + // Then returning so that select can block again. + ssize_t bytes_written_now = + ::write (fd_, data + bytes_written, length - bytes_written); + // read should always return some data as select reported it was + // ready to read when we get to this point. + if (bytes_written_now < 1) { + // Disconnected devices, at least on Linux, show the + // behavior that they are always ready to read immediately + // but reading returns nothing. + throw SerialExecption ("device reports readiness to write but " + "returned no data (device disconnected?)"); + } + // Update bytes_read + bytes_written += static_cast (bytes_written_now); + // If bytes_read == size then we have read everything we need + if (bytes_written == length) { + break; + } + // If bytes_read < size then we have more to read + if (bytes_written < length) { + continue; + } + // If bytes_read > size then we have over read, which shouldn't happen + if (bytes_written > length) { + throw SerialExecption ("read over read, too many bytes where " + "read, this shouldn't happen, might be " + "a logical error!"); + } + } + // This shouldn't happen, if r > 0 our fd has to be in the list! + THROW (IOException, "select reports ready to read, but our fd isn't" + " in the list, this shouldn't happen!"); + } + } + return bytes_written; } void diff --git a/src/impl/win.cc b/src/impl/win.cc new file mode 100644 index 0000000..9b1f6e5 --- /dev/null +++ b/src/impl/win.cc @@ -0,0 +1,549 @@ +/* Copyright 2012 William Woodall and John Harrison */ + +#include "serial/impl/win.h" + +using std::string; +using std::stringstream; +using std::invalid_argument; +using serial::Serial; +using serial::SerialExecption; +using serial::PortNotOpenedException; +using serial::IOException; + + +Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, + bytesize_t bytesize, + parity_t parity, stopbits_t stopbits, + flowcontrol_t flowcontrol) + : port_ (port), fd_ (INVALID_HANDLE_VALUE), is_open_ (false), + baudrate_ (baudrate), parity_ (parity), + bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) +{ + read_mutex = CreateMutex(NULL, false, NULL); + write_mutex = CreateMutex(NULL, false, NULL); + if (port_.empty () == false) + open (); +} + +Serial::SerialImpl::~SerialImpl () +{ + this->close(); + CloseHandle(read_mutex); + CloseHandle(write_mutex); +} + +void +Serial::SerialImpl::open () +{ + if (port_.empty ()) { + throw invalid_argument ("Empty port is invalid."); + } + if (is_open_ == true) { + throw SerialExecption ("Serial port already open."); + } + + fd_ = CreateFile(port_, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + 0); + + if (fd_ == INVALID_HANDLE_VALUE) { + DWORD errno = GetLastError(); + switch (errno) { + case ERROR_FILE_NOT_FOUND: + stringstream ss; + ss << "Specified port, " << port_ << ", does not exist." + THROW (IOException, ss.str().c_str()); + default: + stringstream ss; + ss << "Unknown error opening the serial port: " << errno; + THROW (IOException, ss.str().c_str()); + } + } + + reconfigurePort(); + is_open_ = true; +} + +void +Serial::SerialImpl::reconfigurePort () +{ + if (fd_ == INVALID_HANDLE_VALUE) { + // Can only operate on a valid file descriptor + THROW (IOException, "Invalid file descriptor, is the serial port open?"); + } + + DCB dcbSerialParams = {0}; + + dcbSerial.DCBlength=sizeof(dcbSerialParams); + + if (!GetCommState(fd_, &dcbSerialParams)) { + //error getting state + THROW (IOException, "Error getting the serial port state."); + } + + // setup baud rate + switch (baudrate_) { +#ifdef CBR_0 + case 0: dcbSerialParams.BaudRate = CBR_0; break; +#endif +#ifdef CBR_50 + case 50: dcbSerialParams.BaudRate = CBR_50; break; +#endif +#ifdef CBR_75 + case 75: dcbSerialParams.BaudRate = CBR_75; break; +#endif +#ifdef CBR_110 + case 110: dcbSerialParams.BaudRate = CBR_110; break; +#endif +#ifdef CBR_134 + case 134: dcbSerialParams.BaudRate = CBR_134; break; +#endif +#ifdef CBR_150 + case 150: dcbSerialParams.BaudRate = CBR_150; break; +#endif +#ifdef CBR_200 + case 200: dcbSerialParams.BaudRate = CBR_200; break; +#endif +#ifdef CBR_300 + case 300: dcbSerialParams.BaudRate = CBR_300; break; +#endif +#ifdef CBR_600 + case 600: dcbSerialParams.BaudRate = CBR_600; break; +#endif +#ifdef CBR_1200 + case 1200: dcbSerialParams.BaudRate = CBR_1200; break; +#endif +#ifdef CBR_1800 + case 1800: dcbSerialParams.BaudRate = CBR_1800; break; +#endif +#ifdef CBR_2400 + case 2400: dcbSerialParams.BaudRate = CBR_2400; break; +#endif +#ifdef CBR_4800 + case 4800: dcbSerialParams.BaudRate = CBR_4800; break; +#endif +#ifdef CBR_7200 + case 7200: dcbSerialParams.BaudRate = CBR_7200; break; +#endif +#ifdef CBR_9600 + case 9600: dcbSerialParams.BaudRate = CBR_9600; break; +#endif +#ifdef CBR_14400 + case 14400: dcbSerialParams.BaudRate = CBR_14400; break; +#endif +#ifdef CBR_19200 + case 19200: dcbSerialParams.BaudRate = CBR_19200; break; +#endif +#ifdef CBR_28800 + case 28800: dcbSerialParams.BaudRate = CBR_28800; break; +#endif +#ifdef CBR_57600 + case 57600: dcbSerialParams.BaudRate = CBR_57600; break; +#endif +#ifdef CBR_76800 + case 76800: dcbSerialParams.BaudRate = CBR_76800; break; +#endif +#ifdef CBR_38400 + case 38400: dcbSerialParams.BaudRate = CBR_38400; break; +#endif +#ifdef CBR_115200 + case 115200: dcbSerialParams.BaudRate = CBR_115200; break; +#endif +#ifdef CBR_128000 + case 128000: dcbSerialParams.BaudRate = CBR_128000; break; +#endif +#ifdef CBR_153600 + case 153600: dcbSerialParams.BaudRate = CBR_153600; break; +#endif +#ifdef CBR_230400 + case 230400: dcbSerialParams.BaudRate = CBR_230400; break; +#endif +#ifdef CBR_256000 + case 256000: dcbSerialParams.BaudRate = CBR_256000; break; +#endif +#ifdef CBR_460800 + case 460800: dcbSerialParams.BaudRate = CBR_460800; break; +#endif +#ifdef CBR_921600 + case 921600: dcbSerialParams.BaudRate = CBR_921600; break; +#endif + default: + // Try to blindly assign it + dcbSerialParams.BaudRate = baudrate_; + } + + // setup char len + if (bytesize_ == eightbits) + dcbSerialParams.ByteSize = 8; + else if (bytesize_ == sevenbits) + dcbSerialParams.ByteSize = 7; + else if (bytesize_ == sixbits) + dcbSerialParams.ByteSize = 6; + else if (bytesize_ == fivebits) + dcbSerialParams.ByteSize = 5; + else + throw invalid_argument ("invalid char len"); + + // setup stopbits + if (stopbits_ == stopbits_one) + dcbSerialParams.StopBits = ONESTOPBIT; + else if (stopbits_ == stopbits_one_point_five) + dcbSerialParams.StopBits = ONE5STOPBITS; + else if (stopbits_ == stopbits_two) + dcbSerialParams.StopBits = TWOSTOPBITS; + else + throw invalid_argument ("invalid stop bit"); + + // setup parity + if (parity_ == parity_none) { + dcbSerialParams.Parity = NOPARITY; + } else if (parity_ == parity_even) { + dcbSerialParams.Parity = EVENPARITY; + } else if (parity_ == parity_odd) { + dcbSerialParams.Parity = ODDPARITY; + } else { + throw invalid_argument ("invalid parity"); + } + + // activate settings + if(!SetCommState(fd_, &dcbSerialParams)){ + THROW (IOException, "Error setting serial port settings."); + } +} + +void +Serial::SerialImpl::close () +{ + if (is_open_ == true) { + if (fd_ != INVALID_HANDLE_VALUE) { + CloseHandle(fd_); + fd_ = INVALID_HANDLE_VALUE; + } + is_open_ = false; + } +} + +bool +Serial::SerialImpl::isOpen () const +{ + return is_open_; +} + +size_t +Serial::SerialImpl::available () +{ + THROW (IOException, "available is not implemented on Windows."); +} + +size_t +Serial::SerialImpl::read (uint8_t *buf, size_t size) +{ + if (!is_open_) { + throw PortNotOpenedException ("Serial::read"); + } + DWORD bytes_read; + if (!ReadFile(fd_, buf, size, &bytes_read, NULL)) { + stringstream ss; + ss << "Error while reading from the serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } + return reinterpret_cast (bytes_read); +} + +size_t +Serial::SerialImpl::write (const uint8_t *data, size_t length) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::write"); + } + DWORD bytes_written; + if (!ReadFile(fd_, buf, size, &bytes_written, NULL)) { + stringstream ss; + ss << "Error while writing to the serial port: " << GetLastError(); + THROW (IOException, ss.str().c_str()); + } + return reinterpret_cast (bytes_written); +} + +void +Serial::SerialImpl::setPort (const string &port) +{ + port_ = port; +} + +string +Serial::SerialImpl::getPort () const +{ + return port_; +} + +void +Serial::SerialImpl::setTimeout (serial::Timeout &timeout) +{ + timeout_ = timeout; + COMMTIMEOUTS timeouts = {0}; + timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout; + timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant; + timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier; + timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant; + timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier; + if(!SetCommTimeouts(fd_, &timeouts)){ + THROW (IOException, "Error setting timeouts."); + } +} + +serial::Timeout +Serial::SerialImpl::getTimeout () const +{ + return timeout_; +} + +void +Serial::SerialImpl::setBaudrate (unsigned long baudrate) +{ + baudrate_ = baudrate; + if (is_open_) + reconfigurePort (); +} + +unsigned long +Serial::SerialImpl::getBaudrate () const +{ + return baudrate_; +} + +void +Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) +{ + bytesize_ = bytesize; + if (is_open_) + reconfigurePort (); +} + +serial::bytesize_t +Serial::SerialImpl::getBytesize () const +{ + return bytesize_; +} + +void +Serial::SerialImpl::setParity (serial::parity_t parity) +{ + parity_ = parity; + if (is_open_) + reconfigurePort (); +} + +serial::parity_t +Serial::SerialImpl::getParity () const +{ + return parity_; +} + +void +Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) +{ + stopbits_ = stopbits; + if (is_open_) + reconfigurePort (); +} + +serial::stopbits_t +Serial::SerialImpl::getStopbits () const +{ + return stopbits_; +} + +void +Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) +{ + flowcontrol_ = flowcontrol; + if (is_open_) + reconfigurePort (); +} + +serial::flowcontrol_t +Serial::SerialImpl::getFlowcontrol () const +{ + return flowcontrol_; +} + +void +Serial::SerialImpl::flush () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::flush"); + } + FlushFileBuffers (fd_); +} + +void +Serial::SerialImpl::flushInput () +{ + THROW (IOException, "flushInput is not supported on Windows."); +} + +void +Serial::SerialImpl::flushOutput () +{ + THROW (IOException, "flushOutput is not supported on Windows."); +} + +void +Serial::SerialImpl::sendBreak (int duration) +{ + THROW (IOException, "sendBreak is not supported on Windows."); +} + +void +Serial::SerialImpl::setBreak (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setBreak"); + } + if (level) { + EscapeCommFunction (fd_, SETBREAK); + } else { + EscapeCommFunction (fd_, CLRBREAK); + } +} + +void +Serial::SerialImpl::setRTS (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setRTS"); + } + if (level) { + EscapeCommFunction (fd_, SETRTS); + } else { + EscapeCommFunction (fd_, CLRRTS); + } +} + +void +Serial::SerialImpl::setDTR (bool level) +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::setDTR"); + } + if (level) { + EscapeCommFunction (fd_, SETDTR); + } else { + EscapeCommFunction (fd_, CLRDTR); + } +} + +bool +Serial::SerialImpl::waitForChange () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::waitForChange"); + } + DWORD dwCommEvent; + + if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { + // Error setting communications mask + return false; + } + + if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) { + // An error occurred waiting for the event. + return false; + } else { + // Event has occurred. + return true; + } +} + +bool +Serial::SerialImpl::getCTS () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCTS"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) + // Error in GetCommModemStatus; + THROW (IOException, "Error getting the status of the CTS line."); + + return MS_CTS_ON & dwModemStatus; +} + +bool +Serial::SerialImpl::getDSR () +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getDSR"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) + // Error in GetCommModemStatus; + THROW (IOException, "Error getting the status of the DSR line."); + + return MS_DSR_ON & dwModemStatus; +} + +bool +Serial::SerialImpl::getRI() +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getRI"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) + // Error in GetCommModemStatus; + THROW (IOException, "Error getting the status of the DSR line."); + + return MS_RING_ON & dwModemStatus; +} + +bool +Serial::SerialImpl::getCD() +{ + if (is_open_ == false) { + throw PortNotOpenedException ("Serial::getCD"); + } + DWORD dwModemStatus; + if (!GetCommModemStatus(fd_, &dwModemStatus)) + // Error in GetCommModemStatus; + THROW (IOException, "Error getting the status of the DSR line."); + + return MS_RLSD_ON & dwModemStatus; +} + +void +Serial::SerialImpl::readLock() +{ + if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) { + THROW (IOException, "Error claiming read mutex."); + } +} + +void +Serial::SerialImpl::readUnlock() +{ + if (!ReleaseMutex(read_mutex)) { + THROW (IOException, "Error releasing read mutex."); + } +} + +void +Serial::SerialImpl::writeLock() +{ + if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) { + THROW (IOException, "Error claiming write mutex."); + } +} + +void +Serial::SerialImpl::writeUnlock() +{ + if (!ReleaseMutex(write_mutex)) { + THROW (IOException, "Error releasing write mutex."); + } +} diff --git a/src/impl/windows.cc b/src/impl/windows.cc deleted file mode 100644 index 5e82227..0000000 --- a/src/impl/windows.cc +++ /dev/null @@ -1,670 +0,0 @@ -/* Copyright 2012 William Woodall and John Harrison */ - -#include "serial/impl/windows.h" - -using std::string; -using std::invalid_argument; -using serial::Serial; -using serial::SerialExecption; -using serial::PortNotOpenedException; -using serial::IOException; - - -Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, - long timeout, bytesize_t bytesize, - parity_t parity, stopbits_t stopbits, - flowcontrol_t flowcontrol) -: port_ (port), fd_ (-1), isOpen_ (false), xonxoff_ (true), rtscts_ (false), - timeout_ (timeout), baudrate_ (baudrate), parity_ (parity), bytesize_ (bytesize), - stopbits_ (stopbits), flowcontrol_ (flowcontrol) -{ - if (port_.empty () == false) - open (); -} - -Serial::SerialImpl::~SerialImpl () -{ - close(); -} - -void -Serial::SerialImpl::open () -{ - if (port_.empty()) - { - throw invalid_argument ("bad port specified"); - } - if (isOpen_ == true) - { - throw SerialExecption ("port already open"); - } - - fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); - - if (fd_ == -1) - { - switch (errno) - { - case EINTR: - // Recurse because this is a recoverable error. - open (); - return; - case ENFILE: - case EMFILE: - throw IOException ("to many file handles open"); - break; - default: - throw IOException (errno); - } - } - - reconfigurePort(); - isOpen_ = true; -} - -void -Serial::SerialImpl::reconfigurePort () -{ - if (fd_ == -1) - { - // Can only operate on a valid file descriptor - throw IOException ("invalid file descriptor"); - } - - struct termios options; // The options for the file descriptor - - if (tcgetattr(fd_, &options) == -1) - { - throw IOException ("::tcgetattr"); - } - - // set up raw mode / no echo / binary - options.c_cflag |= (unsigned long) (CLOCAL|CREAD); - options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL| - ISIG|IEXTEN); //|ECHOPRT - - options.c_oflag &= (unsigned long) ~(OPOST); - options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK); -#ifdef IUCLC - options.c_iflag &= (unsigned long) ~IUCLC; -#endif -#ifdef PARMRK - options.c_iflag &= (unsigned long) ~PARMRK; -#endif - - // setup baud rate - bool custom_baud = false; - speed_t baud; - switch (baudrate_) - { -#ifdef B0 - case 0: baud = B0; break; -#endif -#ifdef B50 - case 50: baud = B50; break; -#endif -#ifdef B75 - case 75: baud = B75; break; -#endif -#ifdef B110 - case 110: baud = B110; break; -#endif -#ifdef B134 - case 134: baud = B134; break; -#endif -#ifdef B150 - case 150: baud = B150; break; -#endif -#ifdef B200 - case 200: baud = B200; break; -#endif -#ifdef B300 - case 300: baud = B300; break; -#endif -#ifdef B600 - case 600: baud = B600; break; -#endif -#ifdef B1200 - case 1200: baud = B1200; break; -#endif -#ifdef B1800 - case 1800: baud = B1800; break; -#endif -#ifdef B2400 - case 2400: baud = B2400; break; -#endif -#ifdef B4800 - case 4800: baud = B4800; break; -#endif -#ifdef B7200 - case 7200: baud = B7200; break; -#endif -#ifdef B9600 - case 9600: baud = B9600; break; -#endif -#ifdef B14400 - case 14400: baud = B14400; break; -#endif -#ifdef B19200 - case 19200: baud = B19200; break; -#endif -#ifdef B28800 - case 28800: baud = B28800; break; -#endif -#ifdef B57600 - case 57600: baud = B57600; break; -#endif -#ifdef B76800 - case 76800: baud = B76800; break; -#endif -#ifdef B38400 - case 38400: baud = B38400; break; -#endif -#ifdef B115200 - case 115200: baud = B115200; break; -#endif -#ifdef B128000 - case 128000: baud = B128000; break; -#endif -#ifdef B153600 - case 153600: baud = B153600; break; -#endif -#ifdef B230400 - case 230400: baud = B230400; break; -#endif -#ifdef B256000 - case 256000: baud = B256000; break; -#endif -#ifdef B460800 - case 460800: baud = B460800; break; -#endif -#ifdef B921600 - case 921600: baud = B921600; break; -#endif - default: - custom_baud = true; -// Mac OS X 10.x Support -#if defined(__APPLE__) && defined(__MACH__) -#define IOSSIOSPEED _IOW('T', 2, speed_t) - int new_baud = static_cast (baudrate_); - if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) - { - throw IOException (errno); - } -// Linux Support -#elif defined(__linux__) - struct serial_struct ser; - ioctl(fd_, TIOCGSERIAL, &ser); - // set custom divisor - ser.custom_divisor = ser.baud_base / baudrate_; - // update flags - ser.flags &= ~ASYNC_SPD_MASK; - ser.flags |= ASYNC_SPD_CUST; - - if (ioctl(fd_, TIOCSSERIAL, ser) < 0) - { - throw IOException (errno); - } -#else - throw invalid_argument ("OS does not currently support custom bauds"); -#endif - } - if (custom_baud == false) - { -#ifdef _BSD_SOURCE - ::cfsetspeed(&options, baud); -#else - ::cfsetispeed(&options, baud); - ::cfsetospeed(&options, baud); -#endif - } - - // setup char len - options.c_cflag &= (unsigned long) ~CSIZE; - if (bytesize_ == EIGHTBITS) - options.c_cflag |= CS8; - else if (bytesize_ == SEVENBITS) - options.c_cflag |= CS7; - else if (bytesize_ == SIXBITS) - options.c_cflag |= CS6; - else if (bytesize_ == FIVEBITS) - options.c_cflag |= CS5; - else - throw invalid_argument ("invalid char len"); - // setup stopbits - if (stopbits_ == STOPBITS_ONE) - options.c_cflag &= (unsigned long) ~(CSTOPB); - else if (stopbits_ == STOPBITS_ONE_POINT_FIVE) - options.c_cflag |= (CSTOPB); // XXX same as TWO.. there is no POSIX support for 1.5 - else if (stopbits_ == STOPBITS_TWO) - options.c_cflag |= (CSTOPB); - else - throw invalid_argument ("invalid stop bit"); - // setup parity - options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP); - if (parity_ == PARITY_NONE) - { - options.c_cflag &= (unsigned long) ~(PARENB|PARODD); - } - else if (parity_ == PARITY_EVEN) - { - options.c_cflag &= (unsigned long) ~(PARODD); - options.c_cflag |= (PARENB); - } - else if (parity_ == PARITY_ODD) - { - options.c_cflag |= (PARENB|PARODD); - } - else - { - throw invalid_argument ("invalid parity"); - } - // setup flow control - // xonxoff -#ifdef IXANY - if (xonxoff_) - options.c_iflag |= (IXON|IXOFF); //|IXANY) - else - options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY); -#else - if (xonxoff_) - options.c_iflag |= (IXON|IXOFF); - else - options.c_iflag &= (unsigned long) ~(IXON|IXOFF); -#endif - // rtscts -#ifdef CRTSCTS - if (rtscts_) - options.c_cflag |= (CRTSCTS); - else - options.c_cflag &= (unsigned long) ~(CRTSCTS); -#elif defined CNEW_RTSCTS - if (rtscts_) - options.c_cflag |= (CNEW_RTSCTS); - else - options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS); -#else -#error "OS Support seems wrong." -#endif - - options.c_cc[VMIN] = 1; // Minimum of 1 character in the buffer - options.c_cc[VTIME] = 0; // timeout on waiting for new data - - // activate settings - ::tcsetattr (fd_, TCSANOW, &options); -} - -void -Serial::SerialImpl::close () -{ - if (isOpen_ == true) - { - if (fd_ != -1) - { - ::close (fd_); // Ignoring the outcome - fd_ = -1; - } - isOpen_ = false; - } -} - -bool -Serial::SerialImpl::isOpen () const -{ - return isOpen_; -} - -size_t -Serial::SerialImpl::available () -{ - if (!isOpen_) - { - return 0; - } - int count = 0; - int result = ioctl (fd_, TIOCINQ, &count); - if (result == 0) - { - return static_cast (count); - } - else - { - throw IOException (errno); - } -} - -size_t -Serial::SerialImpl::read (char* buf, size_t size) -{ - if (!isOpen_) - { - throw PortNotOpenedException ("Serial::read"); - } - fd_set readfds; - ssize_t bytes_read = 0; - int count = 0; - while (true) - { - count++; - if (timeout_ != -1) - { - FD_ZERO (&readfds); - FD_SET (fd_, &readfds); - struct timeval timeout; - timeout.tv_sec = timeout_ / 1000; - timeout.tv_usec = static_cast (timeout_ % 1000) * 1000; - int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); - - if (r == -1 && errno == EINTR) - continue; - - if (r == -1) - { - throw IOException (errno); - } - } - - if (timeout_ == -1 || FD_ISSET (fd_, &readfds)) - { - bytes_read = ::read (fd_, buf, size); - // read should always return some data as select reported it was - // ready to read when we get to this point. - if (bytes_read < 1) - { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to read immediately - // but reading returns nothing. - throw SerialExecption ("device reports readiness to read but " - "returned no data (device disconnected?)"); - } - break; - } - else - { - break; - } - } - return static_cast (bytes_read); -} - -size_t -Serial::SerialImpl::write (const string &data) -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::write"); - } - - fd_set writefds; - ssize_t bytes_written = 0; - while (true) - { - if (timeout_ != -1) - { - FD_ZERO (&writefds); - FD_SET (fd_, &writefds); - struct timeval timeout; - timeout.tv_sec = timeout_ / 1000; - timeout.tv_usec = static_cast (timeout_ % 1000) * 1000; - int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout); - - if (r == -1 && errno == EINTR) - continue; - - if (r == -1) - { - throw IOException (errno); - } - } - - if (timeout_ == -1 || FD_ISSET (fd_, &writefds)) - { - bytes_written = ::write (fd_, data.c_str (), data.length ()); - // read should always return some data as select reported it was - // ready to read when we get to this point. - if (bytes_written < 1) - { - // Disconnected devices, at least on Linux, show the - // behavior that they are always ready to read immediately - // but reading returns nothing. - throw SerialExecption ("device reports readiness to read but " - "returned no data (device disconnected?)"); - } - break; - } - else - { - break; - } - } - - return static_cast (bytes_written); -} - -void -Serial::SerialImpl::setPort (const string &port) -{ - port_ = port; -} - -string -Serial::SerialImpl::getPort () const -{ - return port_; -} - -void -Serial::SerialImpl::setTimeout (long timeout) -{ - timeout_ = timeout; -} - -long -Serial::SerialImpl::getTimeout () const -{ - return timeout_; -} - -void -Serial::SerialImpl::setBaudrate (unsigned long baudrate) -{ - baudrate_ = baudrate; - if (isOpen_) - reconfigurePort (); -} - -unsigned long -Serial::SerialImpl::getBaudrate () const -{ - return baudrate_; -} - -void -Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize) -{ - bytesize_ = bytesize; - if (isOpen_) - reconfigurePort (); -} - -serial::bytesize_t -Serial::SerialImpl::getBytesize () const -{ - return bytesize_; -} - -void -Serial::SerialImpl::setParity (serial::parity_t parity) -{ - parity_ = parity; - if (isOpen_) - reconfigurePort (); -} - -serial::parity_t -Serial::SerialImpl::getParity () const -{ - return parity_; -} - -void -Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits) -{ - stopbits_ = stopbits; - if (isOpen_) - reconfigurePort (); -} - -serial::stopbits_t -Serial::SerialImpl::getStopbits () const -{ - return stopbits_; -} - -void -Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol) -{ - flowcontrol_ = flowcontrol; - if (isOpen_) - reconfigurePort (); -} - -serial::flowcontrol_t -Serial::SerialImpl::getFlowcontrol () const -{ - return flowcontrol_; -} - -void -Serial::SerialImpl::flush () -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::flush"); - } - tcdrain (fd_); -} - -void -Serial::SerialImpl::flushInput () -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::flushInput"); - } - tcflush (fd_, TCIFLUSH); -} - -void -Serial::SerialImpl::flushOutput () -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::flushOutput"); - } - tcflush (fd_, TCOFLUSH); -} - -void -Serial::SerialImpl::sendBreak (int duration) -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::sendBreak"); - } - tcsendbreak (fd_, static_cast (duration/4)); -} - -void -Serial::SerialImpl::setBreak (bool level) -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::setBreak"); - } - if (level) - { - ioctl (fd_, TIOCSBRK); - } - else { - ioctl (fd_, TIOCCBRK); - } -} - -void -Serial::SerialImpl::setRTS (bool level) -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::setRTS"); - } - if (level) - { - ioctl (fd_, TIOCMBIS, TIOCM_RTS); - } - else { - ioctl (fd_, TIOCMBIC, TIOCM_RTS); - } -} - -void -Serial::SerialImpl::setDTR (bool level) -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::setDTR"); - } - if (level) - { - ioctl (fd_, TIOCMBIS, TIOCM_DTR); - } - else - { - ioctl (fd_, TIOCMBIC, TIOCM_DTR); - } -} - -bool -Serial::SerialImpl::getCTS () -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::getCTS"); - } - int s = ioctl (fd_, TIOCMGET, 0); - return (s & TIOCM_CTS) != 0; -} - -bool -Serial::SerialImpl::getDSR() -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::getDSR"); - } - int s = ioctl(fd_, TIOCMGET, 0); - return (s & TIOCM_DSR) != 0; -} - -bool -Serial::SerialImpl::getRI() -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::getRI"); - } - int s = ioctl (fd_, TIOCMGET, 0); - return (s & TIOCM_RI) != 0; -} - -bool -Serial::SerialImpl::getCD() -{ - if (isOpen_ == false) - { - throw PortNotOpenedException ("Serial::getCD"); - } - int s = ioctl (fd_, TIOCMGET, 0); - return (s & TIOCM_CD) != 0; -} - diff --git a/src/serial.cc b/src/serial.cc index d391202..67336bc 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -48,7 +48,7 @@ private: SerialImpl *pimpl_; }; -Serial::Serial (const string &port, unsigned long baudrate, Timeout timeout, +Serial::Serial (const string &port, uint32_t baudrate, Timeout timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) : read_cache_("") @@ -88,23 +88,23 @@ Serial::available () } size_t -Serial::read_ (unsigned char *buffer, size_t size) +Serial::read_ (uint8_t *buffer, size_t size) { return this->pimpl_->read (buffer, size); } size_t -Serial::read (unsigned char *buffer, size_t size) +Serial::read (uint8_t *buffer, size_t size) { ScopedReadLock (this->pimpl_); return this->pimpl_->read (buffer, size); } size_t -Serial::read (std::vector &buffer, size_t size) +Serial::read (std::vector &buffer, size_t size) { ScopedReadLock (this->pimpl_); - unsigned char *buffer_ = new unsigned char[size]; + uint8_t *buffer_ = new uint8_t[size]; size_t bytes_read = this->pimpl_->read (buffer_, size); buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); delete[] buffer_; @@ -115,7 +115,7 @@ size_t Serial::read (std::string &buffer, size_t size) { ScopedReadLock (this->pimpl_); - unsigned char *buffer_ = new unsigned char[size]; + uint8_t *buffer_ = new uint8_t[size]; size_t bytes_read = this->pimpl_->read (buffer_, size); buffer.append (reinterpret_cast(buffer_), bytes_read); delete[] buffer_; @@ -135,8 +135,8 @@ Serial::readline (string &buffer, size_t size, string eol) { ScopedReadLock (this->pimpl_); size_t eol_len = eol.length (); - unsigned char *buffer_ = static_cast - (alloca (size * sizeof (unsigned char))); + uint8_t *buffer_ = static_cast + (alloca (size * sizeof (uint8_t))); size_t read_so_far = 0; while (true) { @@ -171,8 +171,8 @@ Serial::readlines (size_t size, string eol) ScopedReadLock (this->pimpl_); std::vector lines; size_t eol_len = eol.length (); - unsigned char *buffer_ = static_cast - (alloca (size * sizeof (unsigned char))); + uint8_t *buffer_ = static_cast + (alloca (size * sizeof (uint8_t))); size_t read_so_far = 0; size_t start_of_line = 0; while (read_so_far < size) { @@ -210,7 +210,28 @@ size_t Serial::write (const string &data) { ScopedWriteLock(this->pimpl_); - return pimpl_->write (data); + return this->write_ (reinterpret_cast(data.c_str()), + data.length()); +} + +size_t +Serial::write (const std::vector &data) +{ + ScopedWriteLock(this->pimpl_); + return this->write_ (&data[0], data.size()); +} + +size_t +Serial::write (const uint8_t *data, size_t size) +{ + ScopedWriteLock(this->pimpl_); + return this->write_(data, size); +} + +size_t +Serial::write_ (const uint8_t *data, size_t length) +{ + return pimpl_->write (data, length); } void @@ -242,15 +263,15 @@ Serial::getTimeout () const { } void -Serial::setBaudrate (unsigned long baudrate) +Serial::setBaudrate (uint32_t baudrate) { pimpl_->setBaudrate (baudrate); } -unsigned long +uint32_t Serial::getBaudrate () const { - return pimpl_->getBaudrate (); + return uint32_t(pimpl_->getBaudrate ()); } void From 5ebd00cde19de4ca957618ae3191e748a321bd85 Mon Sep 17 00:00:00 2001 From: William Woodall Date: Wed, 6 Jun 2012 18:58:14 -0500 Subject: [PATCH 10/16] Removing a vestigial file --- serial.sublime-workspace | 605 --------------------------------------- 1 file changed, 605 deletions(-) delete mode 100644 serial.sublime-workspace diff --git a/serial.sublime-workspace b/serial.sublime-workspace deleted file mode 100644 index 9fa9b00..0000000 --- a/serial.sublime-workspace +++ /dev/null @@ -1,605 +0,0 @@ -{ - "auto_complete": - { - "selected_items": - [ - [ - "baudr", - "baudrate_" - ], - [ - "dcb", - "dcbSerialParams" - ], - [ - "byte", - "bytes_written size_t" - ], - [ - "write", - "write_timeout_multiplier int32_t" - ], - [ - "read", - "read_timeout_multiplier" - ], - [ - "read_", - "read_timeout_multiplier" - ], - [ - "inter", - "inter_byte_timeout" - ], - [ - "write_", - "write_timeout_constant" - ], - [ - "string", - "stringstream" - ], - [ - "Seri", - "SerialExecption" - ], - [ - "tour", - "toupper(int _c) int" - ], - [ - "rotat", - "SceneObject::rotateTo(GLfloat roll, GLfloat pitch, GLfloat yaw) void" - ], - [ - "tou", - "touring_index size_t" - ], - [ - "person", - "person_mbb Model::CollisionBox" - ], - [ - "SE", - "SE Model::CollisionBox" - ], - [ - "m", - "mbb Model::CollisionBox" - ], - [ - "glVer", - "glVertex2fv(const GLfloat *v) void" - ], - [ - "di", - "distance GLfloat" - ], - [ - "the", - "their_position GLfloat *" - ], - [ - "their", - "their_obj_it vector::iterator" - ], - [ - "my", - "my_obj_it vector::iterator" - ], - [ - "my_mod", - "my_model_it vector::iterator" - ], - [ - "thei", - "their_model_it vector::iterator" - ], - [ - "iterator", - "assign(_InputIterator __first, _InputIterator __last) void" - ], - [ - "get", - "getPosition() GLfloat *" - ], - [ - "lh", - "lhs_mbb Model::CollisionBox" - ], - [ - "cal", - "calculateMBB(Model::Object &obj) Model::CollisionBox" - ], - [ - "Col", - "CollisionBox " - ], - [ - "spo", - "spotlight LightingStyle" - ], - [ - "main", - "main_camera Camera" - ], - [ - "pers", - "person Person *" - ], - [ - "glro", - "glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "glTran", - "glTranslatef(GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "she", - "shelby_model string" - ], - [ - "loa", - "loaded_ bool" - ], - [ - "ena", - "enabled_ bool" - ], - [ - "sp", - "specular(GLfloat r, GLfloat g, GLfloat b, GLfloat a) void" - ], - [ - "en", - "direction(GLfloat x, GLfloat y, GLfloat z) void" - ], - [ - "spot", - "spot_light Light" - ], - [ - "GL_NOR", - "GL_NORMALIZE " - ], - [ - "att", - "attenuation_q_ GLfloat" - ], - [ - "atte", - "attenuation_c_ GLfloat" - ], - [ - "glPop", - "glPopMatrix() void" - ], - [ - "appl", - "apply_() void" - ], - [ - "no_l", - "no_lights_left const size_t" - ], - [ - "ligh", - "lights_left size_t" - ], - [ - "do", - "do_normals bool" - ], - [ - "back_in", - "back_inserter(_Container &__x) back_insert_iterator<_Container>" - ], - [ - "istr", - "istream_iterator " - ], - [ - "is", - "istringstream " - ], - [ - "math", - "matches size_t" - ], - [ - "curr", - "current_object Model::Object" - ], - [ - "matc", - "matches2 size_t" - ], - [ - "QwtPlot", - "QwtPlotZoomer" - ], - [ - "__init", - "__initZooming" - ], - [ - "plot_coi", - "plot_coil2" - ], - [ - "plo", - "plot_coil1" - ], - [ - "plot_co", - "plot_coil2" - ], - [ - "QwtPl", - "QwtPlotCurve" - ], - [ - "trail", - "trailer_plotcurve" - ], - [ - "pl", - "plot_coil1" - ], - [ - "plot", - "plot_coil1" - ], - [ - "open", - "open_button" - ], - [ - "plotcoi", - "plot_coil1" - ], - [ - "EM", - "EM61MK2Log" - ], - [ - "pa", - "path_file_name" - ], - [ - "head", - "headings" - ], - [ - "eas", - "eastings" - ], - [ - "north", - "northings" - ], - [ - "las", - "last_east" - ], - [ - "odom", - "odom" - ], - [ - "logs", - "logs_data" - ], - [ - "plot_", - "plot_em61mk2logs" - ], - [ - "Em61", - "EM61MK2Log" - ], - [ - "sib", - "sibling_file_name" - ], - [ - "si", - "sibling_file_name" - ], - [ - "fil", - "file_name" - ] - ] - }, - "buffers": - [ - ], - "build_system": "Packages/Python/Python.sublime-build", - "command_palette": - { - "height": 87.0, - "selected_items": - [ - [ - "convert sp", - "Indentation: Convert to Spaces" - ], - [ - "install", - "Package Control: Install Package" - ], - [ - "Package Control: remo", - "Package Control: Remove Package" - ], - [ - "late", - "LaTeXTools: View PDF" - ] - ], - "width": 449.0 - }, - "console": - { - "height": 0.0 - }, - "distraction_free": - { - "menu_visible": true, - "show_minimap": false, - "show_open_files": false, - "show_tabs": false, - "side_bar_visible": false, - "status_bar_visible": false - }, - "file_history": - [ - "/Users/william/devel/serial/include/serial/serial.h", - "/Users/william/devel/serial/include/serial/impl/win.h", - "/Users/william/devel/serial/src/impl/win.cc", - "/Users/william/devel/serial/src/impl/unix.cc", - "/Users/william/devel/serial/include/serial/impl/unix.h", - "/Users/william/devel/serial/src/serial.cc", - "/Users/william/devel/serial/Findserial.cmake", - "/Users/william/devel/serial/src/impl/windows.cc", - "/Users/william/devel/serial/serial.sublime-project", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings", - "/Users/william/devel/serial/README.md", - "/Users/william/devel/serial/doc/html/serial_8h.html", - "/Users/william/devel/serial/doc/html/unix_8h.html", - "/Users/william/devel/serial/doc/html/windows_8h.html", - "/Users/william/devel/serial/include/serial/impl/windows.h", - "/Users/william/devel/serial/doc/Doxyfile", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/Terminal/Default (OSX).sublime-keymap", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/SublimeAStyleFormatter.sublime-settings", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap", - "/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/Default (OSX).sublime-keymap", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/survey.csv", - "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/image_generator.py", - "/Users/william/.ros/rosdep.yaml", - "/Users/william/.bashrc", - "/Users/william/devel/xbow400/include/xbow_400.h", - "/Users/william/devel/xbow400/src/xbow_400.cpp", - "/Users/william/devel/xbow400/README", - "/Users/william/devel/xbow400/xbow400.sublime-project", - "/Users/william/devel/comp6400/homework6/homework6.sublime-project", - "/Users/william/devel/comp6400/homework6/src/main.cc", - "/Users/william/devel/comp6400/homework6/models/student.obj", - "/Users/william/devel/comp6400/homework6/models/ground.obj", - "/Users/william/devel/comp6400/homework6/models/shelby.obj", - "/Users/william/devel/comp6400/homework6/models/ground.mtl", - "/Users/william/devel/comp6400/homework6/models/shelby.mtl", - "/Users/william/devel/comp6400/homework6/CMakeLists.txt", - "/Users/william/devel/comp6400/homework6/models/shelby.blend", - "/Users/william/devel/comp6400/homework6/Makefile", - "/usr/include/c++/4.2.1/tr1/cstdio", - "/Users/william/devel/comp6400/homework6/src/michaels.cc", - "/Users/william/devel/auxos_orig/scripts/plot_em.py", - "/Users/william/devel/auxos_orig/scripts/logtool.py", - "/Users/william/devel/auxos_orig/scripts/em61mk2.py", - "/Users/william/devel/auxos_orig/scripts/lib/__init__.py", - "/usr/local/Library/Formula/pyqt.rb", - "/usr/local/Library/Formula/pyqwt.rb", - "/Users/william/devel/3dteleop_ws/3d_teleop/redo_slam_offline/launch/play_and_remap_tf.launch", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/launch/automow_stuff.launch", - "/Users/william/devel/auxos_orig/scripts/coords2path.py", - "/Users/william/Downloads/sup1_waypts_utm_path.txt", - "/Users/william/Downloads/example.txt", - "/Users/william/devel/auxos_orig/scripts/sup1_waypts_utm_path.txt", - "/Users/william/devel/ion_plans_paper/citations.bib", - "/Users/william/devel/ion_plans_paper/ion_plans.tex", - "/Users/william/Desktop/em61mk2.py", - "/Users/william/devel/ion_plans_paper/ion_plans.log", - "/Users/william/devel/ion_plans_paper/ion_plans.pdf", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OcTree.h", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.h", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/OccupancyOcTreeBase.hxx", - "/Users/william/devel/3dteleop_ws/octomap/octomap/src/OcTree.cpp", - "/Users/william/devel/3dteleop_ws/octomap/octomap/include/octomap/octomap_deprecated.h", - "/Users/william/devel/3dteleop_ws/octomap/CMakeLists.txt", - "/Users/william/devel/comp6400/homework3/src/main.cc", - "/Users/william/Desktop/untitled.obj", - "/Users/william/devel/cs373-tests/util.py", - "/Users/william/devel/cs373-tests/2.6/code.py", - "/Users/william/devel/cs373-tests/2.6/template.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/manifest.xml", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/odom2tf.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/automow_laser_filter.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/rename_tf_frame.py", - "/Users/william/devel/3dteleop_ws/3d_teleop/misc_scripts/nodes/remap_tf.py", - "/Users/william/Downloads/orocos_kinematics_dynamics-ffdeaad-install_name_tool.patch", - "/Users/william/devel/automow_ws/au_automow_common/automow_bringup/launch/minimal.launch", - "/Users/william/devel/vis_ws/visualization/rviz/manifest.xml", - "/Library/Python/2.7/site-packages/pkg_resources.py", - "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.py", - "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/plot_em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert/Feb 15 - Feb 20/em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/em61mk2.py", - "/Volumes/Storage/Data/Camp Sibert 2-15to2-20/plot_em61mk2.py" - ], - "find": - { - "height": 35.0 - }, - "find_in_files": - { - "height": 93.0, - "where_history": - [ - "", - "" - ] - }, - "find_state": - { - "case_sensitive": false, - "find_history": - [ - "flowcon", - "xonxoff_", - "rtscts_", - "#ifdef B", - "baud = B", - "write", - "char", - "unsigned char", - "char", - "long", - "2011", - " *", - "cts", - " ", - "o ", - "Cube_Cube.001", - "min[2]", - "min[1]", - "max[2]", - "max[1]", - "max[0]", - "min[0]", - "window_width", - "800", - "•", - "Cube", - "expected 1.", - "counter", - "go", - "setZoomerMousePattern", - "updateNode", - "compute", - "insertS" - ], - "highlight": true, - "in_selection": false, - "preserve_case": false, - "regex": false, - "replace_history": - [ - "#ifdef CBR_", - "dcbSerialParams.BaudRate = CBR_", - "2012", - " *", - ", ", - "min.z", - "min.y", - "max.z", - "max.y", - "max.x", - "min.x", - "*" - ], - "reverse": false, - "show_context": true, - "use_buffer2": true, - "whole_word": false, - "wrap": true - }, - "groups": - [ - { - "sheets": - [ - ] - }, - { - "sheets": - [ - ] - } - ], - "incremental_find": - { - "height": 0.0 - }, - "input": - { - "height": 31.0 - }, - "layout": - { - "cells": - [ - [ - 0, - 0, - 1, - 1 - ], - [ - 1, - 0, - 2, - 1 - ] - ], - "cols": - [ - 0.0, - 0.71805886817, - 1.0 - ], - "rows": - [ - 0.0, - 1.0 - ] - }, - "menu_visible": true, - "output.clang": - { - "height": 100.0 - }, - "replace": - { - "height": 64.0 - }, - "save_all_on_build": true, - "select_file": - { - "height": 0.0, - "selected_items": - [ - ], - "width": 0.0 - }, - "select_project": - { - "height": 0.0, - "selected_items": - [ - ], - "width": 0.0 - }, - "show_minimap": false, - "show_open_files": false, - "show_tabs": true, - "side_bar_visible": true, - "side_bar_width": 283.0, - "status_bar_visible": true -} From ead96705dd0a6c5a849378ec5474bf30e47c901b Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 16:44:35 -0500 Subject: [PATCH 11/16] Still working on std types --- include/serial/serial.h | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/include/serial/serial.h b/include/serial/serial.h index 6ad0a5a..5145e0a 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -91,16 +91,6 @@ typedef enum { * in milliseconds. */ struct Timeout { - Timeout (int32_t inter_byte_timeout_=0, int32_t read_timeout_constant_=0, - int32_t read_timeout_multiplier_=0, int32_t write_timeout_constant_=0, - int32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} - /*! * Convenience function to generate Timeout structs using a * single absolute timeout. @@ -115,19 +105,31 @@ struct Timeout { } /*! Number of milliseconds between bytes received to timeout on. */ - int32_t inter_byte_timeout; + uint32_t inter_byte_timeout; /*! A constant number of milliseconds to wait after calling read. */ - int32_t read_timeout_constant; + uint32_t read_timeout_constant; /*! A multiplier against the number of requested bytes to wait after * calling read. */ - int32_t read_timeout_multiplier; + uint32_t read_timeout_multiplier; /*! A constant number of milliseconds to wait after calling write. */ - int32_t write_timeout_constant; + uint32_t write_timeout_constant; /*! A multiplier against the number of requested bytes to wait after * calling write. */ - int32_t write_timeout_multiplier; + uint32_t write_timeout_multiplier; + + typedef std::numeric_limits::max() max; + + Timeout (unsigned int32_t inter_byte_timeout_=0, unsigned int32_t read_timeout_constant_=0, + uint32_t read_timeout_multiplier_=0, uint32_t write_timeout_constant_=0, + uint32_t write_timeout_multiplier_=0) + : inter_byte_timeout(inter_byte_timeout_), + read_timeout_constant(read_timeout_constant_), + read_timeout_multiplier(read_timeout_multiplier_), + write_timeout_constant(write_timeout_constant_), + write_timeout_multiplier(write_timeout_multiplier_) + {} }; /*! From 565ba66271be97890db45869ebf7b65d22d9607a Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 17:49:05 -0500 Subject: [PATCH 12/16] Sorted out the stdint stuff by including a header from the v8 project. --- include/serial/serial.h | 89 ++++++++++++++++++++------------------- include/serial/v8stdint.h | 57 +++++++++++++++++++++++++ serial.cmake | 1 + serial.sublime-project | 2 +- 4 files changed, 104 insertions(+), 45 deletions(-) create mode 100644 include/serial/v8stdint.h diff --git a/include/serial/serial.h b/include/serial/serial.h index 5145e0a..db57ba6 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ __LINE__, (message) ) @@ -89,47 +89,48 @@ typedef enum { /*! * Structure for setting the timeout of the serial port, times are * in milliseconds. + * + * In order to disable the interbyte timeout, set it to Timeout::max(). */ struct Timeout { - /*! - * Convenience function to generate Timeout structs using a - * single absolute timeout. - * - * \param timeout A long that defines the time in milliseconds until a - * timeout occurs after a call to read or write is made. - * - * \return Timeout struct that represents this simple timeout provided. - */ - static Timeout simpleTimeout(long timeout) { - return Timeout(0, timeout, 0, timeout, 0); - } + static uint32_t max() {return std::numeric_limits::max();} + /*! + * Convenience function to generate Timeout structs using a + * single absolute timeout. + * + * \param timeout A long that defines the time in milliseconds until a + * timeout occurs after a call to read or write is made. + * + * \return Timeout struct that represents this simple timeout provided. + */ + static Timeout simpleTimeout(uint32_t timeout) { + return Timeout(max(), timeout, 0, timeout, 0); + } - /*! Number of milliseconds between bytes received to timeout on. */ - uint32_t inter_byte_timeout; - /*! A constant number of milliseconds to wait after calling read. */ - uint32_t read_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling read. - */ - uint32_t read_timeout_multiplier; - /*! A constant number of milliseconds to wait after calling write. */ - uint32_t write_timeout_constant; - /*! A multiplier against the number of requested bytes to wait after - * calling write. - */ - uint32_t write_timeout_multiplier; + /*! Number of milliseconds between bytes received to timeout on. */ + uint32_t inter_byte_timeout; + /*! A constant number of milliseconds to wait after calling read. */ + uint32_t read_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling read. + */ + uint32_t read_timeout_multiplier; + /*! A constant number of milliseconds to wait after calling write. */ + uint32_t write_timeout_constant; + /*! A multiplier against the number of requested bytes to wait after + * calling write. + */ + uint32_t write_timeout_multiplier; - typedef std::numeric_limits::max() max; - - Timeout (unsigned int32_t inter_byte_timeout_=0, unsigned int32_t read_timeout_constant_=0, - uint32_t read_timeout_multiplier_=0, uint32_t write_timeout_constant_=0, - uint32_t write_timeout_multiplier_=0) - : inter_byte_timeout(inter_byte_timeout_), - read_timeout_constant(read_timeout_constant_), - read_timeout_multiplier(read_timeout_multiplier_), - write_timeout_constant(write_timeout_constant_), - write_timeout_multiplier(write_timeout_multiplier_) - {} + Timeout (uint32_t inter_byte_timeout_=0, uint32_t read_timeout_constant_=0, + uint32_t read_timeout_multiplier_=0, uint32_t write_timeout_constant_=0, + uint32_t write_timeout_multiplier_=0) + : inter_byte_timeout(inter_byte_timeout_), + read_timeout_constant(read_timeout_constant_), + read_timeout_multiplier(read_timeout_multiplier_), + write_timeout_constant(write_timeout_constant_), + write_timeout_multiplier(write_timeout_multiplier_) + {} }; /*! @@ -145,7 +146,7 @@ public: * which would be something like 'COM1' on Windows and '/dev/ttyS0' * on Linux. * - * \param baudrate An integer that represents the baudrate + * \param baudrate An unsigned 32-bit integer that represents the baudrate * * \param timeout A serial::Timeout struct that defines the timeout * conditions for the serial port. \see serial::Timeout @@ -402,13 +403,13 @@ public: /*! Sets the timeout for reads and writes. */ void - setTimeout (int32_t inter_byte_timeout, int32_t read_timeout_constant, - int32_t read_timeout_multiplier, int32_t write_timeout_constant, - int32_t write_timeout_multiplier) + setTimeout (uint32_t inter_byte_timeout, uint32_t read_timeout_constant, + uint32_t read_timeout_multiplier, uint32_t write_timeout_constant, + uint32_t write_timeout_multiplier) { Timeout timeout(inter_byte_timeout, read_timeout_constant, - read_timeout_multiplier, write_timeout_constant, - write_timeout_multiplier); + read_timeout_multiplier, write_timeout_constant, + write_timeout_multiplier); return setTimeout(timeout); } diff --git a/include/serial/v8stdint.h b/include/serial/v8stdint.h new file mode 100644 index 0000000..ca0db6b --- /dev/null +++ b/include/serial/v8stdint.h @@ -0,0 +1,57 @@ +// This header is from the v8 google project: +// http://code.google.com/p/v8/source/browse/trunk/include/v8stdint.h + +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Load definitions of standard types. + +#ifndef V8STDINT_H_ +#define V8STDINT_H_ + +#include +#include + +#if defined(_WIN32) && !defined(__MINGW32__) + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; // NOLINT +typedef unsigned short uint16_t; // NOLINT +typedef int int32_t; +typedef unsigned int uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +// intptr_t and friends are defined in crtdefs.h through stdio.h. + +#else + +#include + +#endif + +#endif // V8STDINT_H_ diff --git a/serial.cmake b/serial.cmake index ed63438..1f422cd 100644 --- a/serial.cmake +++ b/serial.cmake @@ -122,6 +122,7 @@ macro(build_serial) ) INSTALL(FILES include/serial/serial.h + include/serial/v8stdint.h DESTINATION include/serial) IF(NOT CMAKE_FIND_INSTALL_PATH) diff --git a/serial.sublime-project b/serial.sublime-project index c6270a1..65e92d9 100644 --- a/serial.sublime-project +++ b/serial.sublime-project @@ -13,7 +13,7 @@ [ "-I/usr/include", "-I/usr/local/include", - "-I/usr/lib/clang/3.1/include/", + // "-I/usr/lib/clang/3.1/include/", "-I${folder:${project_path:serial.sublime-project}}/include" ] } From 088fcda295ce3f29d1d98f58b0ef7b0790cd8e6c Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 17:52:14 -0500 Subject: [PATCH 13/16] Disabling copy constructors on the expections --- include/serial/serial.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/serial/serial.h b/include/serial/serial.h index db57ba6..406825a 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -615,6 +615,10 @@ private: class SerialExecption : public std::exception { + // Disable copy constructors + SerialExecption(const SerialExecption&); + void operator=(const SerialExecption&); + const SerialExecption& operator=(SerialExecption); const char* e_what_; public: SerialExecption (const char *description) : e_what_ (description) {} @@ -629,6 +633,10 @@ public: class IOException : public std::exception { + // Disable copy constructors + IOException(const IOException&); + void operator=(const IOException&); + const IOException& operator=(IOException); std::string file_; int line_; const char* e_what_; @@ -656,6 +664,10 @@ public: class PortNotOpenedException : public std::exception { + // Disable copy constructors + PortNotOpenedException(const PortNotOpenedException&); + void operator=(const PortNotOpenedException&); + const PortNotOpenedException& operator=(PortNotOpenedException); const char * e_what_; public: PortNotOpenedException (const char * description) : e_what_ (description) {} From 7714615af7db36aef2c0c8c08ac4d028d5a11fea Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 17:54:11 -0500 Subject: [PATCH 14/16] Disabling more copy constructors --- src/serial.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/serial.cc b/src/serial.cc index 67336bc..40df96a 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -33,6 +33,11 @@ public: this->pimpl_->readUnlock(); } private: + // Disable copy constructors + ScopedReadLock(const ScopedReadLock&); + void operator=(const ScopedReadLock&); + const ScopedReadLock& operator=(ScopedReadLock); + SerialImpl *pimpl_; }; @@ -45,6 +50,10 @@ public: this->pimpl_->writeUnlock(); } private: + // Disable copy constructors + ScopedWriteLock(const ScopedWriteLock&); + void operator=(const ScopedWriteLock&); + const ScopedWriteLock& operator=(ScopedWriteLock); SerialImpl *pimpl_; }; From ef8265a535b1a3ed7a8e2e905995ba331e4c308a Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 18:01:18 -0500 Subject: [PATCH 15/16] A small change to quiet warnings in linux --- src/serial.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/serial.cc b/src/serial.cc index 40df96a..dc27d01 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -60,10 +60,9 @@ private: Serial::Serial (const string &port, uint32_t baudrate, Timeout timeout, bytesize_t bytesize, parity_t parity, stopbits_t stopbits, flowcontrol_t flowcontrol) - : read_cache_("") + : read_cache_(""), pimpl_(new SerialImpl (port, baudrate, bytesize, parity, + stopbits, flowcontrol)) { - pimpl_ = new SerialImpl (port, baudrate, bytesize, parity, - stopbits, flowcontrol); pimpl_->setTimeout(timeout); } From e12955a560147508f5b051f79866320f7f21a2fc Mon Sep 17 00:00:00 2001 From: William Woodall Date: Thu, 7 Jun 2012 18:09:51 -0500 Subject: [PATCH 16/16] Fixed some issues with the copy constructors --- include/serial/serial.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/serial/serial.h b/include/serial/serial.h index 406825a..fa128cf 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -616,12 +616,14 @@ private: class SerialExecption : public std::exception { // Disable copy constructors - SerialExecption(const SerialExecption&); void operator=(const SerialExecption&); const SerialExecption& operator=(SerialExecption); const char* e_what_; public: SerialExecption (const char *description) : e_what_ (description) {} + SerialExecption (const SerialExecption& other) { + e_what_ = other.e_what_; + } virtual const char* what () const throw () { @@ -634,7 +636,6 @@ public: class IOException : public std::exception { // Disable copy constructors - IOException(const IOException&); void operator=(const IOException&); const IOException& operator=(IOException); std::string file_; @@ -647,6 +648,9 @@ public: explicit IOException (std::string file, int line, const char * description) : file_(file), line_(line), e_what_ (description), errno_(0) {} virtual ~IOException() throw() {} + IOException (const IOException& other) { + e_what_ = other.e_what_; + } int getErrorNumber () { return errno_; } @@ -665,12 +669,14 @@ public: class PortNotOpenedException : public std::exception { // Disable copy constructors - PortNotOpenedException(const PortNotOpenedException&); void operator=(const PortNotOpenedException&); const PortNotOpenedException& operator=(PortNotOpenedException); const char * e_what_; public: PortNotOpenedException (const char * description) : e_what_ (description) {} + PortNotOpenedException (const PortNotOpenedException& other) { + e_what_ = other.e_what_; + } virtual const char* what () const throw () {