1
0
mirror of https://github.com/wjwwood/serial.git synced 2026-01-22 03:34:53 +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
# 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

View File

@ -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

View File

@ -43,7 +43,8 @@
#include <exception>
#include <stdexcept>
#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<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
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<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
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 ();

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 <string.h>
#include <sstream>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <errno.h>
#include <paths.h>
#include <sysexits.h>
@ -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<int> (baudrate_);
if (ioctl (fd_, IOSSIOSPEED, &new_baud, 1) < 0)
{
THROW (IOException, errno);
}
// Linux Support
int new_baud = static_cast<int> (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<size_t> (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<int> (timeout_ % 1000) * 1000;
while (bytes_read < size)
{
timeout.tv_sec = timeout_.read_timeout_constant / 1000;
timeout.tv_usec = static_cast<int> (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<int> ((end.tv_nsec-start.tv_nsec)/1000);
diff.tv_sec = end.tv_sec - start.tv_sec;
diff.tv_usec = static_cast<int> ((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<size_t> (::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<int> (duration/4));
tcsendbreak (fd_, static_cast<int> (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);

View File

@ -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 ();