1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 19:54:57 +08:00

Updating the API to fix some inconsistencies

This commit is contained in:
William Woodall 2012-05-02 00:45:23 -05:00
parent 81fc77dd47
commit 8022c1b1ea
7 changed files with 1119 additions and 337 deletions

View File

@ -37,7 +37,7 @@ PROJECT_NUMBER = 1.0
# for a project that appears at the top of each page and should give viewer # 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. # 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 # 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 # included in the documentation. The maximum height of the logo should not

View File

@ -54,7 +54,6 @@ class serial::Serial::SerialImpl {
public: public:
SerialImpl (const string &port, SerialImpl (const string &port,
unsigned long baudrate, unsigned long baudrate,
long timeout,
bytesize_t bytesize, bytesize_t bytesize,
parity_t parity, parity_t parity,
stopbits_t stopbits, stopbits_t stopbits,
@ -75,7 +74,7 @@ public:
available (); available ();
size_t size_t
read (unsigned char* buf, size_t size = 1); read (unsigned char *buf, size_t size = 1);
size_t size_t
write (const string &data); write (const string &data);
@ -90,28 +89,31 @@ public:
flushOutput (); flushOutput ();
void void
sendBreak(int duration); sendBreak (int duration);
void void
setBreak(bool level); setBreak (bool level);
void void
setRTS(bool level); setRTS (bool level);
void void
setDTR(bool level); setDTR (bool level);
bool bool
getCTS(); waitForChange ();
bool bool
getDSR(); getCTS ();
bool bool
getRI(); getDSR ();
bool bool
getCD(); getRI ();
bool
getCD ();
void void
setPort (const string &port); setPort (const string &port);
@ -120,9 +122,9 @@ public:
getPort () const; getPort () const;
void void
setTimeout (long timeout); setTimeout (timeout_t &timeout);
long timeout_t
getTimeout () const; getTimeout () const;
void void
@ -156,16 +158,16 @@ public:
getFlowcontrol () const; getFlowcontrol () const;
void void
readLock(); readLock ();
void void
readUnlock(); readUnlock ();
void void
writeLock(); writeLock ();
void void
writeUnlock(); writeUnlock ();
protected: protected:
void reconfigurePort (); void reconfigurePort ();
@ -178,7 +180,7 @@ private:
bool xonxoff_; bool xonxoff_;
bool rtscts_; bool rtscts_;
long timeout_; // Timeout for read operations timeout_t timeout_; // Timeout for read operations
unsigned long baudrate_; // Baudrate unsigned long baudrate_; // Baudrate
parity_t parity_; // Parity parity_t parity_; // Parity

View File

@ -43,7 +43,8 @@
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, __LINE__, (message) ) #define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \
__LINE__, (message) )
namespace serial { namespace serial {
@ -83,27 +84,50 @@ typedef enum {
flowcontrol_software flowcontrol_software
} flowcontrol_t; } 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 that provides a portable serial port interface.
*/ */
class Serial { class Serial {
public: 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, * \param port A std::string containing the address of the serial port,
* which would be something like 'COM1' on Windows and '/dev/ttyS0' * which would be something like 'COM1' on Windows and '/dev/ttyS0'
* on Linux. * on Linux.
* *
* \param baudrate An integer that represents the buadrate * \param baudrate An integer that represents the baudrate
*
* \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 bytesize Size of each byte in the serial transmission of data, * \param bytesize Size of each byte in the serial transmission of data,
* default is eightbits, possible values are: fivebits, sixbits, sevenbits, * default is eightbits, possible values are: fivebits, sixbits, sevenbits,
@ -119,14 +143,10 @@ public:
* flowcontrol_none, possible values are: flowcontrol_none, * flowcontrol_none, possible values are: flowcontrol_none,
* flowcontrol_software, flowcontrol_hardware * flowcontrol_software, flowcontrol_hardware
* *
* \param buffer_size The maximum size of the internal buffer, defaults
* to 256 bytes (2^8).
*
* \throw PortNotOpenedException * \throw PortNotOpenedException
*/ */
Serial (const std::string &port = "", Serial (const std::string &port = "",
unsigned long baudrate = 9600, unsigned long baudrate = 9600,
long timeout = 0,
bytesize_t bytesize = eightbits, bytesize_t bytesize = eightbits,
parity_t parity = parity_none, parity_t parity = parity_none,
stopbits_t stopbits = stopbits_one, stopbits_t stopbits = stopbits_one,
@ -136,8 +156,8 @@ public:
virtual ~Serial (); virtual ~Serial ();
/*! /*!
* Opens the serial port as long as the portname is set and the port isn't * Opens the serial port as long as the port is set and the port isn't
* alreay open. * already open.
* *
* If the port is provided to the constructor then an explicit call to open * If the port is provided to the constructor then an explicit call to open
* is not needed. * is not needed.
@ -164,28 +184,82 @@ public:
/*! Return the number of characters in the buffer. */ /*! Return the number of characters in the buffer. */
size_t size_t
available(); available ();
/*! Read a given amount of bytes from the serial port. /*! Read a given amount of bytes from the serial port into a given buffer.
* *
* If a timeout is set it may return less characters than requested. With * The read function will return in one of three cases:
* no timeout it will block until the requested number of bytes have been * * The number of requested bytes was read.
* read or until an exception occurs. * * 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. * \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 size_t
read (unsigned char *buffer, size_t size); 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 size_t
read (std::vector<unsigned char> &buffer, size_t size = 1); read (std::vector<unsigned char> &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 size_t
read (std::string &buffer, size_t size = 1); 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 std::string
read (size_t size = 1); 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. * Reads from the serial port until a single line has been read.
* *
@ -194,15 +268,10 @@ public:
* *
* \return A std::string containing the line. * \return A std::string containing the line.
*/ */
size_t
readline (std::string &buffer,
size_t size = 65536,
std::string eol = "\n");
std::string std::string
readline (size_t size = 65536, readline (size_t size = 65536, std::string eol = "\n");
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 * This requires a timeout > 0 before it can be run. It will read until a
* timeout occurs and return a list of strings. * timeout occurs and return a list of strings.
@ -218,160 +287,207 @@ public:
/*! Write a string to the serial port. /*! 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. * 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 * \return A size_t representing the number of bytes actually written to
* the serial port. * the serial port.
*/ */
size_t size_t
write (const unsigned char *data, size_t size); 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 size_t
write (const std::vector<unsigned char> &data); write (const std::vector<unsigned char> &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 size_t
write (const std::string &data); write (const std::string &data);
/*! Sets the serial port identifier. /*! Sets the serial port identifier.
* *
* \param port A const std::string reference containing the address of the * \param port A const std::string reference containing the address of the
* serial port, which would be something like 'COM1' on Windows and * serial port, which would be something like 'COM1' on Windows and
* '/dev/ttyS0' on Linux. * '/dev/ttyS0' on Linux.
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setPort (const std::string &port); setPort (const std::string &port);
/*! Gets the serial port identifier. /*! Gets the serial port identifier.
* *
* \see Serial::setPort * \see Serial::setPort
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
std::string std::string
getPort () const; getPort () const;
/*! Sets the timeout for reads in milliseconds. /*! Sets the timeout for reads and writes using the timeout_t struct.
* *
* \param timeout A long that represents the time (in milliseconds) until a * There are two basic conditions for timeout described here, the inter byte
* timeout on reads occur. Setting this to zero (0) will cause reading to be * timeout is the maximum amount of time in milliseconds allowed between
* non-blocking, i.e. the available data will be returned immediately, but it * receiving bytes from the serial port. The second condition is where the
* will not block to wait for more. Setting this to a number less than * total timeout expires during a read or write. The total timeout can be
* zero (-1) will result in infinite blocking behaviour, i.e. the serial port * calculated as the multiplier times the number of requested bytes plus the
* will block until either size bytes have been read or an exception has * constant. In this way a single constant time timeout can be specified
* occured. * 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 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. /*! Gets the timeout for reads in seconds.
* *
* \see Serial::setTimeout * \return A timeout_t struct containing the inter_byte_timeout, and read
*/ * and write timeout constants and multipliers.
long *
* \see Serial::setTimeout
*/
timeout_t
getTimeout () const; getTimeout () const;
/*! Sets the baudrate for the serial port. /*! Sets the baudrate for the serial port.
* *
* Possible baudrates depends on the system but some safe baudrates include: * Possible baudrates depends on the system but some safe baudrates include:
* 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000, * 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 56000,
* 57600, 115200 * 57600, 115200
* Some other baudrates that are supported by some comports: * Some other baudrates that are supported by some comports:
* 128000, 153600, 230400, 256000, 460800, 921600 * 128000, 153600, 230400, 256000, 460800, 921600
* *
* \param baudrate An integer that sets the baud rate for the serial port. * \param baudrate An integer that sets the baud rate for the serial port.
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setBaudrate (unsigned long baudrate); setBaudrate (unsigned long baudrate);
/*! Gets the baudrate for the serial port. /*! Gets the baudrate for the serial port.
* *
* \return An integer that sets the baud rate for the serial port. * \return An integer that sets the baud rate for the serial port.
* *
* \see Serial::setBaudrate * \see Serial::setBaudrate
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
unsigned long unsigned long
getBaudrate () const; getBaudrate () const;
/*! Sets the bytesize for the serial port. /*! Sets the bytesize for the serial port.
* *
* \param bytesize Size of each byte in the serial transmission of data, * \param bytesize Size of each byte in the serial transmission of data,
* default is eightbits, possible values are: fivebits, sixbits, sevenbits, * default is eightbits, possible values are: fivebits, sixbits, sevenbits,
* eightbits * eightbits
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setBytesize (bytesize_t bytesize); setBytesize (bytesize_t bytesize);
/*! Gets the bytesize for the serial port. /*! Gets the bytesize for the serial port.
* *
* \see Serial::setBytesize * \see Serial::setBytesize
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
bytesize_t bytesize_t
getBytesize () const; getBytesize () const;
/*! Sets the parity for the serial port. /*! Sets the parity for the serial port.
* *
* \param parity Method of parity, default is parity_none, possible values * \param parity Method of parity, default is parity_none, possible values
* are: parity_none, parity_odd, parity_even * are: parity_none, parity_odd, parity_even
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setParity (parity_t parity); setParity (parity_t parity);
/*! Gets the parity for the serial port. /*! Gets the parity for the serial port.
* *
* \see Serial::setParity * \see Serial::setParity
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
parity_t parity_t
getParity () const; getParity () const;
/*! Sets the stopbits for the serial port. /*! Sets the stopbits for the serial port.
* *
* \param stopbits Number of stop bits used, default is stopbits_one, * \param stopbits Number of stop bits used, default is stopbits_one,
* possible values are: stopbits_one, stopbits_one_point_five, stopbits_two * possible values are: stopbits_one, stopbits_one_point_five, stopbits_two
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setStopbits (stopbits_t stopbits); setStopbits (stopbits_t stopbits);
/*! Gets the stopbits for the serial port. /*! Gets the stopbits for the serial port.
* *
* \see Serial::setStopbits * \see Serial::setStopbits
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
stopbits_t stopbits_t
getStopbits () const; getStopbits () const;
/*! Sets the flow control for the serial port. /*! Sets the flow control for the serial port.
* *
* \param flowcontrol Type of flowcontrol used, default is flowcontrol_none, * \param flowcontrol Type of flowcontrol used, default is flowcontrol_none,
* possible values are: flowcontrol_none, flowcontrol_software, * possible values are: flowcontrol_none, flowcontrol_software,
* flowcontrol_hardware * flowcontrol_hardware
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setFlowcontrol (flowcontrol_t flowcontrol); setFlowcontrol (flowcontrol_t flowcontrol);
/*! Gets the flow control for the serial port. /*! Gets the flow control for the serial port.
* *
* \see Serial::setFlowcontrol * \see Serial::setFlowcontrol
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
flowcontrol_t flowcontrol_t
getFlowcontrol () const; getFlowcontrol () const;
@ -387,27 +503,49 @@ public:
void void
flushOutput (); flushOutput ();
/*! Sends the RS-232 break signal. See tcsendbreak(3). */
void void
sendBreak (int duration); sendBreak (int duration);
/*! Set the break condition to a given level. Defaults to true. */
void void
setBreak (bool level = true); setBreak (bool level = true);
/*! Set the RTS handshaking line to the given level. Defaults to true. */
void void
setRTS (bool level = true); setRTS (bool level = true);
/*! Set the DTR handshaking line to the given level. Defaults to true. */
void void
setDTR (bool level = true); 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 bool
getCTS (); getCTS ();
/*! Returns the current status of the DSR line. */
bool bool
getDSR (); getDSR ();
/*! Returns the current status of the RI line. */
bool bool
getRI (); getRI ();
/*! Returns the current status of the CD line. */
bool bool
getCD (); getCD ();

18
serial.sublime-project Normal file
View File

@ -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"
]
}
}

631
serial.sublime-workspace Normal file
View File

@ -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<Model::Object>::iterator"
],
[
"my",
"my_obj_it vector<Model::Object>::iterator"
],
[
"my_mod",
"my_model_it vector<Model>::iterator"
],
[
"thei",
"their_model_it vector<Model>::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<typename _Tp> "
],
[
"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
}

View File

@ -2,9 +2,11 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sstream>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/signal.h>
#include <errno.h> #include <errno.h>
#include <paths.h> #include <paths.h>
#include <sysexits.h> #include <sysexits.h>
@ -35,6 +37,7 @@
#endif #endif
using std::string; using std::string;
using std::stringstream;
using std::invalid_argument; using std::invalid_argument;
using serial::Serial; using serial::Serial;
using serial::SerialExecption; using serial::SerialExecption;
@ -43,12 +46,12 @@ using serial::IOException;
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate, Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
long timeout, bytesize_t bytesize, bytesize_t bytesize,
parity_t parity, stopbits_t stopbits, parity_t parity, stopbits_t stopbits,
flowcontrol_t flowcontrol) flowcontrol_t flowcontrol)
: port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (true), rtscts_ (false), : port_ (port), fd_ (-1), is_open_ (false), xonxoff_ (true), rtscts_ (false),
timeout_ (timeout), baudrate_ (baudrate), parity_ (parity), baudrate_ (baudrate), parity_ (parity),
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol) bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
{ {
pthread_mutex_init(&this->read_mutex, NULL); pthread_mutex_init(&this->read_mutex, NULL);
pthread_mutex_init(&this->write_mutex, NULL); pthread_mutex_init(&this->write_mutex, NULL);
@ -66,30 +69,26 @@ Serial::SerialImpl::~SerialImpl ()
void void
Serial::SerialImpl::open () Serial::SerialImpl::open ()
{ {
if (port_.empty ()) if (port_.empty ()) {
{
throw invalid_argument ("Empty port is invalid."); throw invalid_argument ("Empty port is invalid.");
} }
if (is_open_ == true) if (is_open_ == true) {
{
throw SerialExecption ("Serial port already open."); throw SerialExecption ("Serial port already open.");
} }
fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd_ == -1) if (fd_ == -1) {
{ switch (errno) {
switch (errno) case EINTR:
{ // Recurse because this is a recoverable error.
case EINTR: open ();
// Recurse because this is a recoverable error. return;
open (); case ENFILE:
return; case EMFILE:
case ENFILE: THROW (IOException, "Too many file handles open.");
case EMFILE: default:
THROW (IOException, "Too many file handles open."); THROW (IOException, errno);
default:
THROW (IOException, errno);
} }
} }
@ -100,26 +99,24 @@ Serial::SerialImpl::open ()
void void
Serial::SerialImpl::reconfigurePort () Serial::SerialImpl::reconfigurePort ()
{ {
if (fd_ == -1) if (fd_ == -1) {
{
// Can only operate on a valid file descriptor // Can only operate on a valid file descriptor
THROW (IOException, "Invalid file descriptor, is the serial port open?"); THROW (IOException, "Invalid file descriptor, is the serial port open?");
} }
struct termios options; // The options for the file descriptor struct termios options; // The options for the file descriptor
if (tcgetattr(fd_, &options) == -1) if (tcgetattr(fd_, &options) == -1) {
{
THROW (IOException, "::tcgetattr"); THROW (IOException, "::tcgetattr");
} }
// set up raw mode / no echo / binary // set up raw mode / no echo / binary
options.c_cflag |= (unsigned long) (CLOCAL|CREAD); options.c_cflag |= (unsigned long) (CLOCAL | CREAD);
options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL| options.c_lflag &= (unsigned long) ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL |
ISIG|IEXTEN); //|ECHOPRT ISIG | IEXTEN); //|ECHOPRT
options.c_oflag &= (unsigned long) ~(OPOST); 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 #ifdef IUCLC
options.c_iflag &= (unsigned long) ~IUCLC; options.c_iflag &= (unsigned long) ~IUCLC;
#endif #endif
@ -130,122 +127,118 @@ Serial::SerialImpl::reconfigurePort ()
// setup baud rate // setup baud rate
bool custom_baud = false; bool custom_baud = false;
speed_t baud; speed_t baud;
switch (baudrate_) switch (baudrate_) {
{
#ifdef B0 #ifdef B0
case 0: baud = B0; break; case 0: baud = B0; break;
#endif #endif
#ifdef B50 #ifdef B50
case 50: baud = B50; break; case 50: baud = B50; break;
#endif #endif
#ifdef B75 #ifdef B75
case 75: baud = B75; break; case 75: baud = B75; break;
#endif #endif
#ifdef B110 #ifdef B110
case 110: baud = B110; break; case 110: baud = B110; break;
#endif #endif
#ifdef B134 #ifdef B134
case 134: baud = B134; break; case 134: baud = B134; break;
#endif #endif
#ifdef B150 #ifdef B150
case 150: baud = B150; break; case 150: baud = B150; break;
#endif #endif
#ifdef B200 #ifdef B200
case 200: baud = B200; break; case 200: baud = B200; break;
#endif #endif
#ifdef B300 #ifdef B300
case 300: baud = B300; break; case 300: baud = B300; break;
#endif #endif
#ifdef B600 #ifdef B600
case 600: baud = B600; break; case 600: baud = B600; break;
#endif #endif
#ifdef B1200 #ifdef B1200
case 1200: baud = B1200; break; case 1200: baud = B1200; break;
#endif #endif
#ifdef B1800 #ifdef B1800
case 1800: baud = B1800; break; case 1800: baud = B1800; break;
#endif #endif
#ifdef B2400 #ifdef B2400
case 2400: baud = B2400; break; case 2400: baud = B2400; break;
#endif #endif
#ifdef B4800 #ifdef B4800
case 4800: baud = B4800; break; case 4800: baud = B4800; break;
#endif #endif
#ifdef B7200 #ifdef B7200
case 7200: baud = B7200; break; case 7200: baud = B7200; break;
#endif #endif
#ifdef B9600 #ifdef B9600
case 9600: baud = B9600; break; case 9600: baud = B9600; break;
#endif #endif
#ifdef B14400 #ifdef B14400
case 14400: baud = B14400; break; case 14400: baud = B14400; break;
#endif #endif
#ifdef B19200 #ifdef B19200
case 19200: baud = B19200; break; case 19200: baud = B19200; break;
#endif #endif
#ifdef B28800 #ifdef B28800
case 28800: baud = B28800; break; case 28800: baud = B28800; break;
#endif #endif
#ifdef B57600 #ifdef B57600
case 57600: baud = B57600; break; case 57600: baud = B57600; break;
#endif #endif
#ifdef B76800 #ifdef B76800
case 76800: baud = B76800; break; case 76800: baud = B76800; break;
#endif #endif
#ifdef B38400 #ifdef B38400
case 38400: baud = B38400; break; case 38400: baud = B38400; break;
#endif #endif
#ifdef B115200 #ifdef B115200
case 115200: baud = B115200; break; case 115200: baud = B115200; break;
#endif #endif
#ifdef B128000 #ifdef B128000
case 128000: baud = B128000; break; case 128000: baud = B128000; break;
#endif #endif
#ifdef B153600 #ifdef B153600
case 153600: baud = B153600; break; case 153600: baud = B153600; break;
#endif #endif
#ifdef B230400 #ifdef B230400
case 230400: baud = B230400; break; case 230400: baud = B230400; break;
#endif #endif
#ifdef B256000 #ifdef B256000
case 256000: baud = B256000; break; case 256000: baud = B256000; break;
#endif #endif
#ifdef B460800 #ifdef B460800
case 460800: baud = B460800; break; case 460800: baud = B460800; break;
#endif #endif
#ifdef B921600 #ifdef B921600
case 921600: baud = B921600; break; case 921600: baud = B921600; break;
#endif #endif
default: default:
custom_baud = true; custom_baud = true;
// Mac OS X 10.x Support // Mac OS X 10.x Support
#if defined(__APPLE__) && defined(__MACH__) #if defined(__APPLE__) && defined(__MACH__)
#define IOSSIOSPEED _IOW('T', 2, speed_t) #define IOSSIOSPEED _IOW('T', 2, speed_t)
int new_baud = static_cast<int> (baudrate_); int new_baud = static_cast<int> (baudrate_);
if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0) {
{ THROW (IOException, errno);
THROW (IOException, errno); }
} // Linux Support
// Linux Support
#elif defined(__linux__) #elif defined(__linux__)
struct serial_struct ser; struct serial_struct ser;
ioctl (fd_, TIOCGSERIAL, &ser); ioctl (fd_, TIOCGSERIAL, &ser);
// set custom divisor // set custom divisor
ser.custom_divisor = ser.baud_base / baudrate_; ser.custom_divisor = ser.baud_base / baudrate_;
// update flags // update flags
ser.flags &= ~ASYNC_SPD_MASK; ser.flags &= ~ASYNC_SPD_MASK;
ser.flags |= ASYNC_SPD_CUST; ser.flags |= ASYNC_SPD_CUST;
if (ioctl (fd_, TIOCSSERIAL, ser) < 0) if (ioctl (fd_, TIOCSSERIAL, ser) < 0) {
{ THROW (IOException, errno);
THROW (IOException, errno); }
}
#else #else
throw invalid_argument ("OS does not currently support custom bauds"); throw invalid_argument ("OS does not currently support custom bauds");
#endif #endif
} }
if (custom_baud == false) if (custom_baud == false) {
{
#ifdef _BSD_SOURCE #ifdef _BSD_SOURCE
::cfsetspeed(&options, baud); ::cfsetspeed(&options, baud);
#else #else
@ -257,56 +250,49 @@ Serial::SerialImpl::reconfigurePort ()
// setup char len // setup char len
options.c_cflag &= (unsigned long) ~CSIZE; options.c_cflag &= (unsigned long) ~CSIZE;
if (bytesize_ == eightbits) if (bytesize_ == eightbits)
options.c_cflag |= CS8; options.c_cflag |= CS8;
else if (bytesize_ == sevenbits) else if (bytesize_ == sevenbits)
options.c_cflag |= CS7; options.c_cflag |= CS7;
else if (bytesize_ == sixbits) else if (bytesize_ == sixbits)
options.c_cflag |= CS6; options.c_cflag |= CS6;
else if (bytesize_ == fivebits) else if (bytesize_ == fivebits)
options.c_cflag |= CS5; options.c_cflag |= CS5;
else else
throw invalid_argument ("invalid char len"); throw invalid_argument ("invalid char len");
// setup stopbits // setup stopbits
if (stopbits_ == stopbits_one) if (stopbits_ == stopbits_one)
options.c_cflag &= (unsigned long) ~(CSTOPB); options.c_cflag &= (unsigned long) ~(CSTOPB);
else if (stopbits_ == stopbits_one_point_five) else if (stopbits_ == stopbits_one_point_five)
// ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5 // ONE POINT FIVE same as TWO.. there is no POSIX support for 1.5
options.c_cflag |= (CSTOPB); options.c_cflag |= (CSTOPB);
else if (stopbits_ == stopbits_two) else if (stopbits_ == stopbits_two)
options.c_cflag |= (CSTOPB); options.c_cflag |= (CSTOPB);
else else
throw invalid_argument ("invalid stop bit"); throw invalid_argument ("invalid stop bit");
// setup parity // setup parity
options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP); options.c_iflag &= (unsigned long) ~(INPCK | ISTRIP);
if (parity_ == parity_none) if (parity_ == parity_none) {
{ options.c_cflag &= (unsigned long) ~(PARENB | PARODD);
options.c_cflag &= (unsigned long) ~(PARENB|PARODD); } else if (parity_ == parity_even) {
}
else if (parity_ == parity_even)
{
options.c_cflag &= (unsigned long) ~(PARODD); options.c_cflag &= (unsigned long) ~(PARODD);
options.c_cflag |= (PARENB); options.c_cflag |= (PARENB);
} } else if (parity_ == parity_odd) {
else if (parity_ == parity_odd) options.c_cflag |= (PARENB | PARODD);
{ } else {
options.c_cflag |= (PARENB|PARODD);
}
else
{
throw invalid_argument ("invalid parity"); throw invalid_argument ("invalid parity");
} }
// setup flow control // setup flow control
// xonxoff // xonxoff
#ifdef IXANY #ifdef IXANY
if (xonxoff_) if (xonxoff_)
options.c_iflag |= (IXON|IXOFF); //|IXANY) options.c_iflag |= (IXON | IXOFF); //|IXANY)
else else
options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY); options.c_iflag &= (unsigned long) ~(IXON | IXOFF | IXANY);
#else #else
if (xonxoff_) if (xonxoff_)
options.c_iflag |= (IXON|IXOFF); options.c_iflag |= (IXON | IXOFF);
else else
options.c_iflag &= (unsigned long) ~(IXON|IXOFF); options.c_iflag &= (unsigned long) ~(IXON | IXOFF);
#endif #endif
// rtscts // rtscts
#ifdef CRTSCTS #ifdef CRTSCTS
@ -337,10 +323,8 @@ Serial::SerialImpl::reconfigurePort ()
void void
Serial::SerialImpl::close () Serial::SerialImpl::close ()
{ {
if (is_open_ == true) if (is_open_ == true) {
{ if (fd_ != -1) {
if (fd_ != -1)
{
::close (fd_); // Ignoring the outcome ::close (fd_); // Ignoring the outcome
fd_ = -1; fd_ = -1;
} }
@ -357,23 +341,20 @@ Serial::SerialImpl::isOpen () const
size_t size_t
Serial::SerialImpl::available () Serial::SerialImpl::available ()
{ {
if (!is_open_) if (!is_open_) {
{
return 0; return 0;
} }
int count = 0; int count = 0;
int result = ioctl (fd_, TIOCINQ, &count); int result = ioctl (fd_, TIOCINQ, &count);
if (result == 0) if (result == 0) {
{
return static_cast<size_t> (count); return static_cast<size_t> (count);
} } else {
else
{
THROW (IOException, errno); 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 # ifdef __MACH__ // OS X does not have clock_gettime, use clock_get_time
clock_serv_t cclock; clock_serv_t cclock;
mach_timespec_t mts; mach_timespec_t mts;
@ -388,19 +369,18 @@ inline void get_time_now(struct timespec &time) {
} }
size_t 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"); throw PortNotOpenedException ("Serial::read");
} }
fd_set readfds; fd_set readfds;
size_t bytes_read = 0; size_t bytes_read = 0;
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = timeout_ / 1000; timeout.tv_sec = timeout_.read_timeout_constant / 1000;
timeout.tv_usec = static_cast<int> (timeout_ % 1000) * 1000; timeout.tv_usec = static_cast<int> (timeout_.read_timeout_constant % 1000);
while (bytes_read < size) timeout.tv_usec *= 1000; // To convert to micro seconds
{ while (bytes_read < size) {
FD_ZERO (&readfds); FD_ZERO (&readfds);
FD_SET (fd_, &readfds); FD_SET (fd_, &readfds);
// On Linux the timeout struct is updated by select to contain the time // On Linux the timeout struct is updated by select to contain the time
@ -418,8 +398,8 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size)
get_time_now(end); get_time_now(end);
// Calculate the time select took // Calculate the time select took
struct timeval diff; struct timeval diff;
diff.tv_sec = end.tv_sec-start.tv_sec; diff.tv_sec = end.tv_sec - start.tv_sec;
diff.tv_usec = static_cast<int> ((end.tv_nsec-start.tv_nsec)/1000); diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
// Update the timeout // Update the timeout
if (timeout.tv_sec <= diff.tv_sec) { if (timeout.tv_sec <= diff.tv_sec) {
timeout.tv_sec = 0; timeout.tv_sec = 0;
@ -434,7 +414,7 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size)
#endif #endif
// Figure out what happened by looking at select's response 'r' // Figure out what happened by looking at select's response 'r'
/** Error **/ /** Error **/
if (r < 0) { if (r < 0) {
// Select was interrupted, try again // Select was interrupted, try again
if (errno == EINTR) { if (errno == EINTR) {
@ -443,22 +423,21 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size)
// Otherwise there was some error // Otherwise there was some error
THROW (IOException, errno); THROW (IOException, errno);
} }
/** Timeout **/ /** Timeout **/
if (r == 0) { if (r == 0) {
break; break;
} }
/** Something ready to read **/ /** Something ready to read **/
if (r > 0) { if (r > 0) {
// Make sure our file descriptor is in the ready to read list // Make sure our file descriptor is in the ready to read list
if (FD_ISSET (fd_, &readfds)) { 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 avaialble now
// Then returning so that select can block again. // Then returning so that select can block again.
ssize_t bytes_read_now = 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 // read should always return some data as select reported it was
// ready to read when we get to this point. // 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 // Disconnected devices, at least on Linux, show the
// behavior that they are always ready to read immediately // behavior that they are always ready to read immediately
// but reading returns nothing. // 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! // 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" 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; return bytes_read;
@ -493,11 +472,9 @@ Serial::SerialImpl::read (unsigned char* buf, size_t size)
size_t size_t
Serial::SerialImpl::write (const string &data) Serial::SerialImpl::write (const string &data)
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::write"); throw PortNotOpenedException ("Serial::write");
} }
return static_cast<size_t> (::write (fd_, data.c_str (), data.length ())); return static_cast<size_t> (::write (fd_, data.c_str (), data.length ()));
} }
@ -514,12 +491,12 @@ Serial::SerialImpl::getPort () const
} }
void void
Serial::SerialImpl::setTimeout (long timeout) Serial::SerialImpl::setTimeout (serial::timeout_t &timeout)
{ {
timeout_ = timeout; timeout_ = timeout;
} }
long serial::timeout_t
Serial::SerialImpl::getTimeout () const Serial::SerialImpl::getTimeout () const
{ {
return timeout_; return timeout_;
@ -598,8 +575,7 @@ Serial::SerialImpl::getFlowcontrol () const
void void
Serial::SerialImpl::flush () Serial::SerialImpl::flush ()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::flush"); throw PortNotOpenedException ("Serial::flush");
} }
tcdrain (fd_); tcdrain (fd_);
@ -608,8 +584,7 @@ Serial::SerialImpl::flush ()
void void
Serial::SerialImpl::flushInput () Serial::SerialImpl::flushInput ()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::flushInput"); throw PortNotOpenedException ("Serial::flushInput");
} }
tcflush (fd_, TCIFLUSH); tcflush (fd_, TCIFLUSH);
@ -618,8 +593,7 @@ Serial::SerialImpl::flushInput ()
void void
Serial::SerialImpl::flushOutput () Serial::SerialImpl::flushOutput ()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::flushOutput"); throw PortNotOpenedException ("Serial::flushOutput");
} }
tcflush (fd_, TCOFLUSH); tcflush (fd_, TCOFLUSH);
@ -628,25 +602,21 @@ Serial::SerialImpl::flushOutput ()
void void
Serial::SerialImpl::sendBreak (int duration) Serial::SerialImpl::sendBreak (int duration)
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::sendBreak"); throw PortNotOpenedException ("Serial::sendBreak");
} }
tcsendbreak (fd_, static_cast<int> (duration/4)); tcsendbreak (fd_, static_cast<int> (duration / 4));
} }
void void
Serial::SerialImpl::setBreak (bool level) Serial::SerialImpl::setBreak (bool level)
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::setBreak"); throw PortNotOpenedException ("Serial::setBreak");
} }
if (level) if (level) {
{
ioctl (fd_, TIOCSBRK); ioctl (fd_, TIOCSBRK);
} } else {
else {
ioctl (fd_, TIOCCBRK); ioctl (fd_, TIOCCBRK);
} }
} }
@ -654,15 +624,12 @@ Serial::SerialImpl::setBreak (bool level)
void void
Serial::SerialImpl::setRTS (bool level) Serial::SerialImpl::setRTS (bool level)
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::setRTS"); throw PortNotOpenedException ("Serial::setRTS");
} }
if (level) if (level) {
{
ioctl (fd_, TIOCMBIS, TIOCM_RTS); ioctl (fd_, TIOCMBIS, TIOCM_RTS);
} } else {
else {
ioctl (fd_, TIOCMBIC, TIOCM_RTS); ioctl (fd_, TIOCMBIC, TIOCM_RTS);
} }
} }
@ -670,25 +637,45 @@ Serial::SerialImpl::setRTS (bool level)
void void
Serial::SerialImpl::setDTR (bool level) Serial::SerialImpl::setDTR (bool level)
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::setDTR"); throw PortNotOpenedException ("Serial::setDTR");
} }
if (level) if (level) {
{
ioctl (fd_, TIOCMBIS, TIOCM_DTR); ioctl (fd_, TIOCMBIS, TIOCM_DTR);
} } else {
else
{
ioctl (fd_, TIOCMBIC, TIOCM_DTR); 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 bool
Serial::SerialImpl::getCTS () Serial::SerialImpl::getCTS ()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::getCTS"); throw PortNotOpenedException ("Serial::getCTS");
} }
int s = ioctl (fd_, TIOCMGET, 0); int s = ioctl (fd_, TIOCMGET, 0);
@ -696,10 +683,9 @@ Serial::SerialImpl::getCTS ()
} }
bool bool
Serial::SerialImpl::getDSR() Serial::SerialImpl::getDSR ()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::getDSR"); throw PortNotOpenedException ("Serial::getDSR");
} }
int s = ioctl (fd_, TIOCMGET, 0); int s = ioctl (fd_, TIOCMGET, 0);
@ -709,8 +695,7 @@ Serial::SerialImpl::getDSR()
bool bool
Serial::SerialImpl::getRI() Serial::SerialImpl::getRI()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::getRI"); throw PortNotOpenedException ("Serial::getRI");
} }
int s = ioctl (fd_, TIOCMGET, 0); int s = ioctl (fd_, TIOCMGET, 0);
@ -720,8 +705,7 @@ Serial::SerialImpl::getRI()
bool bool
Serial::SerialImpl::getCD() Serial::SerialImpl::getCD()
{ {
if (is_open_ == false) if (is_open_ == false) {
{
throw PortNotOpenedException ("Serial::getCD"); throw PortNotOpenedException ("Serial::getCD");
} }
int s = ioctl (fd_, TIOCMGET, 0); int s = ioctl (fd_, TIOCMGET, 0);
@ -729,7 +713,8 @@ Serial::SerialImpl::getCD()
} }
void void
Serial::SerialImpl::readLock() { Serial::SerialImpl::readLock()
{
int result = pthread_mutex_lock(&this->read_mutex); int result = pthread_mutex_lock(&this->read_mutex);
if (result) { if (result) {
THROW (IOException, result); THROW (IOException, result);
@ -737,7 +722,8 @@ Serial::SerialImpl::readLock() {
} }
void void
Serial::SerialImpl::readUnlock() { Serial::SerialImpl::readUnlock()
{
int result = pthread_mutex_unlock(&this->read_mutex); int result = pthread_mutex_unlock(&this->read_mutex);
if (result) { if (result) {
THROW (IOException, result); THROW (IOException, result);
@ -745,7 +731,8 @@ Serial::SerialImpl::readUnlock() {
} }
void void
Serial::SerialImpl::writeLock() { Serial::SerialImpl::writeLock()
{
int result = pthread_mutex_lock(&this->write_mutex); int result = pthread_mutex_lock(&this->write_mutex);
if (result) { if (result) {
THROW (IOException, result); THROW (IOException, result);
@ -753,7 +740,8 @@ Serial::SerialImpl::writeLock() {
} }
void void
Serial::SerialImpl::writeUnlock() { Serial::SerialImpl::writeUnlock()
{
int result = pthread_mutex_unlock(&this->write_mutex); int result = pthread_mutex_unlock(&this->write_mutex);
if (result) { if (result) {
THROW (IOException, result); THROW (IOException, result);

View File

@ -48,12 +48,12 @@ private:
SerialImpl *pimpl_; 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, bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
flowcontrol_t flowcontrol) flowcontrol_t flowcontrol)
: read_cache_("") : read_cache_("")
{ {
pimpl_ = new SerialImpl (port, baudrate, timeout, bytesize, parity, pimpl_ = new SerialImpl (port, baudrate, bytesize, parity,
stopbits, flowcontrol); stopbits, flowcontrol);
} }
@ -230,12 +230,12 @@ Serial::getPort () const
} }
void void
Serial::setTimeout (long timeout) Serial::setTimeout (serial::timeout_t &timeout)
{ {
pimpl_->setTimeout (timeout); pimpl_->setTimeout (timeout);
} }
long serial::timeout_t
Serial::getTimeout () const { Serial::getTimeout () const {
return pimpl_->getTimeout (); return pimpl_->getTimeout ();
} }
@ -341,6 +341,11 @@ void Serial::setDTR (bool level)
pimpl_->setDTR (level); pimpl_->setDTR (level);
} }
bool Serial::waitForChange()
{
return pimpl_->waitForChange();
}
bool Serial::getCTS () bool Serial::getCTS ()
{ {
return pimpl_->getCTS (); return pimpl_->getCTS ();