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

Adding initial windows support.

This commit is contained in:
William Woodall 2012-06-06 18:56:44 -05:00
parent 0a66fa991d
commit 6fac95d633
11 changed files with 847 additions and 862 deletions

1
.gitignore vendored
View File

@ -23,3 +23,4 @@ patched
wiped wiped
msg_gen msg_gen
srv_gen srv_gen
doc/html

View File

@ -1,5 +1,5 @@
find_path(serial_INCLUDE_DIRS serial.h /usr/include/serial find_path(serial_INCLUDE_DIRS serial/serial.h /usr/include
/usr/local/include/serial "$ENV{NAMER_ROOT}") /usr/local/include "$ENV{NAMER_ROOT}")
find_library(serial_LIBRARIES serial /usr/lib /usr/local/lib find_library(serial_LIBRARIES serial /usr/lib /usr/local/lib
"$ENV{NAMER_ROOT}") "$ENV{NAMER_ROOT}")

View File

@ -70,7 +70,7 @@ Run the example:
The BSD License The BSD License
Copyright (c) 2011 William Woodall Copyright (c) 2012 William Woodall
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -8,7 +8,7 @@
* *
* The MIT License * The MIT License
* *
* Copyright (c) 2011 William Woodall, John Harrison * Copyright (c) 2012 William Woodall, John Harrison
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -74,10 +74,10 @@ public:
available (); available ();
size_t size_t
read (unsigned char *buf, size_t size = 1); read (uint8_t *buf, size_t size = 1);
size_t size_t
write (const string &data); write (const uint8_t *data, size_t length);
void void
flush (); flush ();

View File

@ -8,7 +8,7 @@
* *
* The MIT License * The MIT License
* *
* Copyright (c) 2011 William Woodall, John Harrison * Copyright (c) 2012 William Woodall, John Harrison
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -39,6 +39,8 @@
#include "serial/serial.h" #include "serial/serial.h"
#include "windows.h"
namespace serial { namespace serial {
using std::string; using std::string;
@ -51,7 +53,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,
@ -72,10 +73,10 @@ public:
available (); available ();
size_t size_t
read (char* buf, size_t size = 1); read (uint8_t *buf, size_t size = 1);
size_t size_t
write (const string &data); write (const uint8_t *data, size_t length);
void void
flush (); flush ();
@ -98,6 +99,9 @@ public:
void void
setDTR (bool level); setDTR (bool level);
bool
waitForChange ();
bool bool
getCTS (); getCTS ();
@ -117,9 +121,9 @@ public:
getPort () const; getPort () const;
void void
setTimeout (long timeout); setTimeout (Timeout &timeout);
long Timeout
getTimeout () const; getTimeout () const;
void void
@ -152,24 +156,39 @@ public:
flowcontrol_t flowcontrol_t
getFlowcontrol () const; getFlowcontrol () const;
void
readLock ();
void
readUnlock ();
void
writeLock ();
void
writeUnlock ();
protected: protected:
void reconfigurePort (); void reconfigurePort ();
private: private:
string port_; // Path to the file descriptor string port_; // Path to the file descriptor
int fd_; // The current file descriptor HANDLE fd_;
bool isOpen_; bool is_open_;
bool xonxoff_;
bool rtscts_;
long timeout_; // Timeout for read operations Timeout timeout_; // Timeout for read operations
unsigned long baudrate_; // Baudrate unsigned long baudrate_; // Baudrate
parity_t parity_; // Parity parity_t parity_; // Parity
bytesize_t bytesize_; // Size of the bytes bytesize_t bytesize_; // Size of the bytes
stopbits_t stopbits_; // Stop Bits stopbits_t stopbits_; // Stop Bits
flowcontrol_t flowcontrol_; // Flow Control flowcontrol_t flowcontrol_; // Flow Control
// Mutex used to lock the read functions
HANDLE read_mutex;
// Mutex used to lock the write functions
HANDLE write_mutex;
}; };
} }

View File

@ -8,7 +8,7 @@
* *
* The MIT License * The MIT License
* *
* Copyright (c) 2011 William Woodall * Copyright (c) 2012 William Woodall
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -42,6 +42,7 @@
#include <sstream> #include <sstream>
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
#include <stdint.h>
#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \ #define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \
__LINE__, (message) ) __LINE__, (message) )
@ -89,9 +90,9 @@ typedef enum {
* in milliseconds. * in milliseconds.
*/ */
struct Timeout { struct Timeout {
Timeout (long inter_byte_timeout_=0, long read_timeout_constant_=0, Timeout (int32_t inter_byte_timeout_=0, int32_t read_timeout_constant_=0,
long read_timeout_multiplier_=0, long write_timeout_constant_=0, int32_t read_timeout_multiplier_=0, int32_t write_timeout_constant_=0,
long write_timeout_multiplier_=0) int32_t write_timeout_multiplier_=0)
: inter_byte_timeout(inter_byte_timeout_), : inter_byte_timeout(inter_byte_timeout_),
read_timeout_constant(read_timeout_constant_), read_timeout_constant(read_timeout_constant_),
read_timeout_multiplier(read_timeout_multiplier_), read_timeout_multiplier(read_timeout_multiplier_),
@ -99,19 +100,19 @@ struct Timeout {
write_timeout_multiplier(write_timeout_multiplier_) write_timeout_multiplier(write_timeout_multiplier_)
{} {}
/*! Number of milliseconds between bytes received to timeout on. */ /*! Number of milliseconds between bytes received to timeout on. */
long inter_byte_timeout; int32_t inter_byte_timeout;
/*! A constant number of milliseconds to wait after calling read. */ /*! A constant number of milliseconds to wait after calling read. */
long read_timeout_constant; int32_t read_timeout_constant;
/*! A multiplier against the number of requested bytes to wait after /*! A multiplier against the number of requested bytes to wait after
* calling read. * calling read.
*/ */
long read_timeout_multiplier; int32_t read_timeout_multiplier;
/*! A constant number of milliseconds to wait after calling write. */ /*! A constant number of milliseconds to wait after calling write. */
long write_timeout_constant; int32_t write_timeout_constant;
/*! A multiplier against the number of requested bytes to wait after /*! A multiplier against the number of requested bytes to wait after
* calling write. * calling write.
*/ */
long write_timeout_multiplier; int32_t write_timeout_multiplier;
}; };
/*! /*!
@ -149,7 +150,7 @@ public:
* \throw PortNotOpenedException * \throw PortNotOpenedException
*/ */
Serial (const std::string &port = "", Serial (const std::string &port = "",
unsigned long baudrate = 9600, uint32_t baudrate = 9600,
Timeout timeout = Timeout(), Timeout timeout = Timeout(),
bytesize_t bytesize = eightbits, bytesize_t bytesize = eightbits,
parity_t parity = parity_none, parity_t parity = parity_none,
@ -209,25 +210,25 @@ public:
* occur. * occur.
* * An exception occurred, in this case an actual exception will be thrown. * * An exception occurred, in this case an actual exception will be thrown.
* *
* \param buffer An unsigned char array of at least the requested size. * \param buffer An uint8_t array of at least the requested size.
* \param size A size_t defining how many bytes to be read. * \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 * \return A size_t representing the number of bytes read as a result of the
* call to read. * call to read.
*/ */
size_t size_t
read (unsigned char *buffer, size_t size); read (uint8_t *buffer, size_t size);
/*! Read a given amount of bytes from the serial port into a give buffer. /*! Read a given amount of bytes from the serial port into a give buffer.
* *
* \param buffer A reference to a std::vector of unsigned char. * \param buffer A reference to a std::vector of uint8_t.
* \param size A size_t defining how many bytes to be read. * \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 * \return A size_t representing the number of bytes read as a result of the
* call to read. * call to read.
*/ */
size_t size_t
read (std::vector<unsigned char> &buffer, size_t size = 1); read (std::vector<uint8_t> &buffer, size_t size = 1);
/*! Read a given amount of bytes from the serial port into a give buffer. /*! Read a given amount of bytes from the serial port into a give buffer.
* *
@ -301,7 +302,7 @@ public:
* the serial port. * the serial port.
*/ */
size_t size_t
write (const unsigned char *data, size_t size); write (const uint8_t *data, size_t size);
/*! Write a string to the serial port. /*! Write a string to the serial port.
* *
@ -312,7 +313,7 @@ public:
* the serial port. * the serial port.
*/ */
size_t size_t
write (const std::vector<unsigned char> &data); write (const std::vector<uint8_t> &data);
/*! Write a string to the serial port. /*! Write a string to the serial port.
* *
@ -384,9 +385,9 @@ public:
/*! Sets the timeout for reads and writes. */ /*! Sets the timeout for reads and writes. */
void void
setTimeout (long inter_byte_timeout, long read_timeout_constant, setTimeout (int32_t inter_byte_timeout, int32_t read_timeout_constant,
long read_timeout_multiplier, long write_timeout_constant, int32_t read_timeout_multiplier, int32_t write_timeout_constant,
long write_timeout_multiplier) int32_t write_timeout_multiplier)
{ {
Timeout timeout(inter_byte_timeout, read_timeout_constant, Timeout timeout(inter_byte_timeout, read_timeout_constant,
read_timeout_multiplier, write_timeout_constant, read_timeout_multiplier, write_timeout_constant,
@ -417,7 +418,7 @@ public:
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
void void
setBaudrate (unsigned long baudrate); setBaudrate (uint32_t baudrate);
/*! Gets the baudrate for the serial port. /*! Gets the baudrate for the serial port.
* *
@ -427,7 +428,7 @@ public:
* *
* \throw InvalidConfigurationException * \throw InvalidConfigurationException
*/ */
unsigned long uint32_t
getBaudrate () const; getBaudrate () const;
/*! Sets the bytesize for the serial port. /*! Sets the bytesize for the serial port.
@ -587,7 +588,10 @@ private:
// Read common function // Read common function
size_t size_t
read_ (unsigned char *buffer, size_t size); read_ (uint8_t *buffer, size_t size);
// Write common function
size_t
write_ (const uint8_t *data, size_t length);
}; };
@ -646,11 +650,6 @@ public:
} }
}; };
class SerialExceptionBase : public std::exception
{
};
} // namespace serial } // namespace serial
#endif #endif

View File

@ -3,6 +3,46 @@
{ {
"selected_items": "selected_items":
[ [
[
"baudr",
"baudrate_"
],
[
"dcb",
"dcbSerialParams"
],
[
"byte",
"bytes_written size_t"
],
[
"write",
"write_timeout_multiplier int32_t"
],
[
"read",
"read_timeout_multiplier"
],
[
"read_",
"read_timeout_multiplier"
],
[
"inter",
"inter_byte_timeout"
],
[
"write_",
"write_timeout_constant"
],
[
"string",
"stringstream"
],
[
"Seri",
"SerialExecption"
],
[ [
"tour", "tour",
"toupper(int _c) int" "toupper(int _c) int"
@ -275,41 +315,25 @@
}, },
"buffers": "buffers":
[ [
{
"file": "include/serial/serial.h",
"settings":
{
"buffer_size": 17876,
"line_ending": "Unix"
}
},
{
"file": "src/serial.cc",
"settings":
{
"buffer_size": 7015,
"line_ending": "Unix"
}
},
{
"file": "src/impl/unix.cc",
"settings":
{
"buffer_size": 16696,
"line_ending": "Unix"
}
}
], ],
"build_system": "Packages/Python/Python.sublime-build", "build_system": "Packages/Python/Python.sublime-build",
"command_palette": "command_palette":
{ {
"height": 47.0, "height": 87.0,
"selected_items": "selected_items":
[ [
[
"convert sp",
"Indentation: Convert to Spaces"
],
[ [
"install", "install",
"Package Control: Install Package" "Package Control: Install Package"
], ],
[
"Package Control: remo",
"Package Control: Remove Package"
],
[ [
"late", "late",
"LaTeXTools: View PDF" "LaTeXTools: View PDF"
@ -332,6 +356,27 @@
}, },
"file_history": "file_history":
[ [
"/Users/william/devel/serial/include/serial/serial.h",
"/Users/william/devel/serial/include/serial/impl/win.h",
"/Users/william/devel/serial/src/impl/win.cc",
"/Users/william/devel/serial/src/impl/unix.cc",
"/Users/william/devel/serial/include/serial/impl/unix.h",
"/Users/william/devel/serial/src/serial.cc",
"/Users/william/devel/serial/Findserial.cmake",
"/Users/william/devel/serial/src/impl/windows.cc",
"/Users/william/devel/serial/serial.sublime-project",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings",
"/Users/william/devel/serial/README.md",
"/Users/william/devel/serial/doc/html/serial_8h.html",
"/Users/william/devel/serial/doc/html/unix_8h.html",
"/Users/william/devel/serial/doc/html/windows_8h.html",
"/Users/william/devel/serial/include/serial/impl/windows.h",
"/Users/william/devel/serial/doc/Doxyfile",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/Terminal/Default (OSX).sublime-keymap",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/SublimeAStyleFormatter.sublime-settings",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap",
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/Default (OSX).sublime-keymap",
"/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py", "/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_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_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/test_costmap.py",
@ -343,7 +388,6 @@
"/Users/william/devel/xbow400/src/xbow_400.cpp", "/Users/william/devel/xbow400/src/xbow_400.cpp",
"/Users/william/devel/xbow400/README", "/Users/william/devel/xbow400/README",
"/Users/william/devel/xbow400/xbow400.sublime-project", "/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/homework6.sublime-project",
"/Users/william/devel/comp6400/homework6/src/main.cc", "/Users/william/devel/comp6400/homework6/src/main.cc",
"/Users/william/devel/comp6400/homework6/models/student.obj", "/Users/william/devel/comp6400/homework6/models/student.obj",
@ -405,9 +449,10 @@
}, },
"find_in_files": "find_in_files":
{ {
"height": 0.0, "height": 93.0,
"where_history": "where_history":
[ [
"<open files>",
"" ""
] ]
}, },
@ -416,6 +461,18 @@
"case_sensitive": false, "case_sensitive": false,
"find_history": "find_history":
[ [
"flowcon",
"xonxoff_",
"rtscts_",
"#ifdef B",
"baud = B",
"write",
"char",
"unsigned char",
"char",
"long",
"2011",
" *",
"cts", "cts",
" ", " ",
"o ", "o ",
@ -444,6 +501,10 @@
"regex": false, "regex": false,
"replace_history": "replace_history":
[ [
"#ifdef CBR_",
"dcbSerialParams.BaudRate = CBR_",
"2012",
" *",
", ", ", ",
"min.z", "min.z",
"min.y", "min.y",
@ -462,95 +523,8 @@
"groups": "groups":
[ [
{ {
"selected": 2,
"sheets": "sheets":
[ [
{
"buffer": 0,
"file": "include/serial/serial.h",
"settings":
{
"buffer_size": 17876,
"regions":
{
},
"selection":
[
[
11407,
11407
]
],
"settings":
{
"syntax": "Packages/C++/C++.tmLanguage",
"tab_size": 4,
"translate_tabs_to_spaces": true,
"word_wrap": true,
"wrap_width": 80
},
"translation.x": 0.0,
"translation.y": 6934.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 1,
"file": "src/serial.cc",
"settings":
{
"buffer_size": 7015,
"regions":
{
},
"selection":
[
[
0,
0
]
],
"settings":
{
"syntax": "Packages/C++/C++.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 479.0,
"zoom_level": 1.0
},
"type": "text"
},
{
"buffer": 2,
"file": "src/impl/unix.cc",
"settings":
{
"buffer_size": 16696,
"regions":
{
},
"selection":
[
[
15521,
15521
]
],
"settings":
{
"syntax": "Packages/C++/C++.tmLanguage",
"tab_size": 2,
"translate_tabs_to_spaces": true
},
"translation.x": 0.0,
"translation.y": 10013.0,
"zoom_level": 1.0
},
"type": "text"
}
] ]
}, },
{ {
@ -587,7 +561,7 @@
"cols": "cols":
[ [
0.0, 0.0,
0.61784814072, 0.71805886817,
1.0 1.0
], ],
"rows": "rows":

View File

@ -369,7 +369,7 @@ inline void get_time_now(struct timespec &time)
} }
size_t size_t
Serial::SerialImpl::read (unsigned char *buf, size_t size) Serial::SerialImpl::read (uint8_t *buf, size_t size)
{ {
if (!is_open_) { if (!is_open_) {
throw PortNotOpenedException ("Serial::read"); throw PortNotOpenedException ("Serial::read");
@ -470,12 +470,104 @@ Serial::SerialImpl::read (unsigned char *buf, size_t size)
} }
size_t size_t
Serial::SerialImpl::write (const string &data) Serial::SerialImpl::write (const uint8_t *data, size_t length)
{ {
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 ())); fd_set writefds;
size_t bytes_written = 0;
struct timeval timeout;
timeout.tv_sec = timeout_.write_timeout_constant / 1000;
timeout.tv_usec = static_cast<int> (timeout_.write_timeout_multiplier % 1000);
timeout.tv_usec *= 1000; // To convert to micro seconds
while (bytes_written < length) {
FD_ZERO (&writefds);
FD_SET (fd_, &writefds);
// On Linux the timeout struct is updated by select to contain the time
// left on the timeout to make looping easier, but on other platforms this
// does not occur.
#if !defined(__linux__)
// Begin timing select
struct timespec start, end;
get_time_now(start);
#endif
// Do the select
int r = select (fd_ + 1, &writefds, NULL, NULL, &timeout);
#if !defined(__linux__)
// Calculate difference and update the structure
get_time_now(end);
// Calculate the time select took
struct timeval diff;
diff.tv_sec = end.tv_sec - start.tv_sec;
diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
// Update the timeout
if (timeout.tv_sec <= diff.tv_sec) {
timeout.tv_sec = 0;
} else {
timeout.tv_sec -= diff.tv_sec;
}
if (timeout.tv_usec <= diff.tv_usec) {
timeout.tv_usec = 0;
} else {
timeout.tv_usec -= diff.tv_usec;
}
#endif
// Figure out what happened by looking at select's response 'r'
/** Error **/
if (r < 0) {
// Select was interrupted, try again
if (errno == EINTR) {
continue;
}
// Otherwise there was some error
THROW (IOException, errno);
}
/** Timeout **/
if (r == 0) {
break;
}
/** Something ready to read **/
if (r > 0) {
// Make sure our file descriptor is in the ready to read list
if (FD_ISSET (fd_, &writefds)) {
// This should be non-blocking returning only what is avaialble now
// Then returning so that select can block again.
ssize_t bytes_written_now =
::write (fd_, data + bytes_written, length - bytes_written);
// read should always return some data as select reported it was
// ready to read when we get to this point.
if (bytes_written_now < 1) {
// Disconnected devices, at least on Linux, show the
// behavior that they are always ready to read immediately
// but reading returns nothing.
throw SerialExecption ("device reports readiness to write but "
"returned no data (device disconnected?)");
}
// Update bytes_read
bytes_written += static_cast<size_t> (bytes_written_now);
// If bytes_read == size then we have read everything we need
if (bytes_written == length) {
break;
}
// If bytes_read < size then we have more to read
if (bytes_written < length) {
continue;
}
// If bytes_read > size then we have over read, which shouldn't happen
if (bytes_written > length) {
throw SerialExecption ("read over read, too many bytes where "
"read, this shouldn't happen, might be "
"a logical error!");
}
}
// This shouldn't happen, if r > 0 our fd has to be in the list!
THROW (IOException, "select reports ready to read, but our fd isn't"
" in the list, this shouldn't happen!");
}
}
return bytes_written;
} }
void void

549
src/impl/win.cc Normal file
View File

@ -0,0 +1,549 @@
/* Copyright 2012 William Woodall and John Harrison */
#include "serial/impl/win.h"
using std::string;
using std::stringstream;
using std::invalid_argument;
using serial::Serial;
using serial::SerialExecption;
using serial::PortNotOpenedException;
using serial::IOException;
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
bytesize_t bytesize,
parity_t parity, stopbits_t stopbits,
flowcontrol_t flowcontrol)
: port_ (port), fd_ (INVALID_HANDLE_VALUE), is_open_ (false),
baudrate_ (baudrate), parity_ (parity),
bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
{
read_mutex = CreateMutex(NULL, false, NULL);
write_mutex = CreateMutex(NULL, false, NULL);
if (port_.empty () == false)
open ();
}
Serial::SerialImpl::~SerialImpl ()
{
this->close();
CloseHandle(read_mutex);
CloseHandle(write_mutex);
}
void
Serial::SerialImpl::open ()
{
if (port_.empty ()) {
throw invalid_argument ("Empty port is invalid.");
}
if (is_open_ == true) {
throw SerialExecption ("Serial port already open.");
}
fd_ = CreateFile(port_,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (fd_ == INVALID_HANDLE_VALUE) {
DWORD errno = GetLastError();
switch (errno) {
case ERROR_FILE_NOT_FOUND:
stringstream ss;
ss << "Specified port, " << port_ << ", does not exist."
THROW (IOException, ss.str().c_str());
default:
stringstream ss;
ss << "Unknown error opening the serial port: " << errno;
THROW (IOException, ss.str().c_str());
}
}
reconfigurePort();
is_open_ = true;
}
void
Serial::SerialImpl::reconfigurePort ()
{
if (fd_ == INVALID_HANDLE_VALUE) {
// Can only operate on a valid file descriptor
THROW (IOException, "Invalid file descriptor, is the serial port open?");
}
DCB dcbSerialParams = {0};
dcbSerial.DCBlength=sizeof(dcbSerialParams);
if (!GetCommState(fd_, &dcbSerialParams)) {
//error getting state
THROW (IOException, "Error getting the serial port state.");
}
// setup baud rate
switch (baudrate_) {
#ifdef CBR_0
case 0: dcbSerialParams.BaudRate = CBR_0; break;
#endif
#ifdef CBR_50
case 50: dcbSerialParams.BaudRate = CBR_50; break;
#endif
#ifdef CBR_75
case 75: dcbSerialParams.BaudRate = CBR_75; break;
#endif
#ifdef CBR_110
case 110: dcbSerialParams.BaudRate = CBR_110; break;
#endif
#ifdef CBR_134
case 134: dcbSerialParams.BaudRate = CBR_134; break;
#endif
#ifdef CBR_150
case 150: dcbSerialParams.BaudRate = CBR_150; break;
#endif
#ifdef CBR_200
case 200: dcbSerialParams.BaudRate = CBR_200; break;
#endif
#ifdef CBR_300
case 300: dcbSerialParams.BaudRate = CBR_300; break;
#endif
#ifdef CBR_600
case 600: dcbSerialParams.BaudRate = CBR_600; break;
#endif
#ifdef CBR_1200
case 1200: dcbSerialParams.BaudRate = CBR_1200; break;
#endif
#ifdef CBR_1800
case 1800: dcbSerialParams.BaudRate = CBR_1800; break;
#endif
#ifdef CBR_2400
case 2400: dcbSerialParams.BaudRate = CBR_2400; break;
#endif
#ifdef CBR_4800
case 4800: dcbSerialParams.BaudRate = CBR_4800; break;
#endif
#ifdef CBR_7200
case 7200: dcbSerialParams.BaudRate = CBR_7200; break;
#endif
#ifdef CBR_9600
case 9600: dcbSerialParams.BaudRate = CBR_9600; break;
#endif
#ifdef CBR_14400
case 14400: dcbSerialParams.BaudRate = CBR_14400; break;
#endif
#ifdef CBR_19200
case 19200: dcbSerialParams.BaudRate = CBR_19200; break;
#endif
#ifdef CBR_28800
case 28800: dcbSerialParams.BaudRate = CBR_28800; break;
#endif
#ifdef CBR_57600
case 57600: dcbSerialParams.BaudRate = CBR_57600; break;
#endif
#ifdef CBR_76800
case 76800: dcbSerialParams.BaudRate = CBR_76800; break;
#endif
#ifdef CBR_38400
case 38400: dcbSerialParams.BaudRate = CBR_38400; break;
#endif
#ifdef CBR_115200
case 115200: dcbSerialParams.BaudRate = CBR_115200; break;
#endif
#ifdef CBR_128000
case 128000: dcbSerialParams.BaudRate = CBR_128000; break;
#endif
#ifdef CBR_153600
case 153600: dcbSerialParams.BaudRate = CBR_153600; break;
#endif
#ifdef CBR_230400
case 230400: dcbSerialParams.BaudRate = CBR_230400; break;
#endif
#ifdef CBR_256000
case 256000: dcbSerialParams.BaudRate = CBR_256000; break;
#endif
#ifdef CBR_460800
case 460800: dcbSerialParams.BaudRate = CBR_460800; break;
#endif
#ifdef CBR_921600
case 921600: dcbSerialParams.BaudRate = CBR_921600; break;
#endif
default:
// Try to blindly assign it
dcbSerialParams.BaudRate = baudrate_;
}
// setup char len
if (bytesize_ == eightbits)
dcbSerialParams.ByteSize = 8;
else if (bytesize_ == sevenbits)
dcbSerialParams.ByteSize = 7;
else if (bytesize_ == sixbits)
dcbSerialParams.ByteSize = 6;
else if (bytesize_ == fivebits)
dcbSerialParams.ByteSize = 5;
else
throw invalid_argument ("invalid char len");
// setup stopbits
if (stopbits_ == stopbits_one)
dcbSerialParams.StopBits = ONESTOPBIT;
else if (stopbits_ == stopbits_one_point_five)
dcbSerialParams.StopBits = ONE5STOPBITS;
else if (stopbits_ == stopbits_two)
dcbSerialParams.StopBits = TWOSTOPBITS;
else
throw invalid_argument ("invalid stop bit");
// setup parity
if (parity_ == parity_none) {
dcbSerialParams.Parity = NOPARITY;
} else if (parity_ == parity_even) {
dcbSerialParams.Parity = EVENPARITY;
} else if (parity_ == parity_odd) {
dcbSerialParams.Parity = ODDPARITY;
} else {
throw invalid_argument ("invalid parity");
}
// activate settings
if(!SetCommState(fd_, &dcbSerialParams)){
THROW (IOException, "Error setting serial port settings.");
}
}
void
Serial::SerialImpl::close ()
{
if (is_open_ == true) {
if (fd_ != INVALID_HANDLE_VALUE) {
CloseHandle(fd_);
fd_ = INVALID_HANDLE_VALUE;
}
is_open_ = false;
}
}
bool
Serial::SerialImpl::isOpen () const
{
return is_open_;
}
size_t
Serial::SerialImpl::available ()
{
THROW (IOException, "available is not implemented on Windows.");
}
size_t
Serial::SerialImpl::read (uint8_t *buf, size_t size)
{
if (!is_open_) {
throw PortNotOpenedException ("Serial::read");
}
DWORD bytes_read;
if (!ReadFile(fd_, buf, size, &bytes_read, NULL)) {
stringstream ss;
ss << "Error while reading from the serial port: " << GetLastError();
THROW (IOException, ss.str().c_str());
}
return reinterpret_cast<size_t> (bytes_read);
}
size_t
Serial::SerialImpl::write (const uint8_t *data, size_t length)
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::write");
}
DWORD bytes_written;
if (!ReadFile(fd_, buf, size, &bytes_written, NULL)) {
stringstream ss;
ss << "Error while writing to the serial port: " << GetLastError();
THROW (IOException, ss.str().c_str());
}
return reinterpret_cast<size_t> (bytes_written);
}
void
Serial::SerialImpl::setPort (const string &port)
{
port_ = port;
}
string
Serial::SerialImpl::getPort () const
{
return port_;
}
void
Serial::SerialImpl::setTimeout (serial::Timeout &timeout)
{
timeout_ = timeout;
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout;
timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant;
timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier;
timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant;
timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier;
if(!SetCommTimeouts(fd_, &timeouts)){
THROW (IOException, "Error setting timeouts.");
}
}
serial::Timeout
Serial::SerialImpl::getTimeout () const
{
return timeout_;
}
void
Serial::SerialImpl::setBaudrate (unsigned long baudrate)
{
baudrate_ = baudrate;
if (is_open_)
reconfigurePort ();
}
unsigned long
Serial::SerialImpl::getBaudrate () const
{
return baudrate_;
}
void
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize)
{
bytesize_ = bytesize;
if (is_open_)
reconfigurePort ();
}
serial::bytesize_t
Serial::SerialImpl::getBytesize () const
{
return bytesize_;
}
void
Serial::SerialImpl::setParity (serial::parity_t parity)
{
parity_ = parity;
if (is_open_)
reconfigurePort ();
}
serial::parity_t
Serial::SerialImpl::getParity () const
{
return parity_;
}
void
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits)
{
stopbits_ = stopbits;
if (is_open_)
reconfigurePort ();
}
serial::stopbits_t
Serial::SerialImpl::getStopbits () const
{
return stopbits_;
}
void
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol)
{
flowcontrol_ = flowcontrol;
if (is_open_)
reconfigurePort ();
}
serial::flowcontrol_t
Serial::SerialImpl::getFlowcontrol () const
{
return flowcontrol_;
}
void
Serial::SerialImpl::flush ()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::flush");
}
FlushFileBuffers (fd_);
}
void
Serial::SerialImpl::flushInput ()
{
THROW (IOException, "flushInput is not supported on Windows.");
}
void
Serial::SerialImpl::flushOutput ()
{
THROW (IOException, "flushOutput is not supported on Windows.");
}
void
Serial::SerialImpl::sendBreak (int duration)
{
THROW (IOException, "sendBreak is not supported on Windows.");
}
void
Serial::SerialImpl::setBreak (bool level)
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::setBreak");
}
if (level) {
EscapeCommFunction (fd_, SETBREAK);
} else {
EscapeCommFunction (fd_, CLRBREAK);
}
}
void
Serial::SerialImpl::setRTS (bool level)
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::setRTS");
}
if (level) {
EscapeCommFunction (fd_, SETRTS);
} else {
EscapeCommFunction (fd_, CLRRTS);
}
}
void
Serial::SerialImpl::setDTR (bool level)
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::setDTR");
}
if (level) {
EscapeCommFunction (fd_, SETDTR);
} else {
EscapeCommFunction (fd_, CLRDTR);
}
}
bool
Serial::SerialImpl::waitForChange ()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::waitForChange");
}
DWORD dwCommEvent;
if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) {
// Error setting communications mask
return false;
}
if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) {
// An error occurred waiting for the event.
return false;
} else {
// Event has occurred.
return true;
}
}
bool
Serial::SerialImpl::getCTS ()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getCTS");
}
DWORD dwModemStatus;
if (!GetCommModemStatus(fd_, &dwModemStatus))
// Error in GetCommModemStatus;
THROW (IOException, "Error getting the status of the CTS line.");
return MS_CTS_ON & dwModemStatus;
}
bool
Serial::SerialImpl::getDSR ()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getDSR");
}
DWORD dwModemStatus;
if (!GetCommModemStatus(fd_, &dwModemStatus))
// Error in GetCommModemStatus;
THROW (IOException, "Error getting the status of the DSR line.");
return MS_DSR_ON & dwModemStatus;
}
bool
Serial::SerialImpl::getRI()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getRI");
}
DWORD dwModemStatus;
if (!GetCommModemStatus(fd_, &dwModemStatus))
// Error in GetCommModemStatus;
THROW (IOException, "Error getting the status of the DSR line.");
return MS_RING_ON & dwModemStatus;
}
bool
Serial::SerialImpl::getCD()
{
if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getCD");
}
DWORD dwModemStatus;
if (!GetCommModemStatus(fd_, &dwModemStatus))
// Error in GetCommModemStatus;
THROW (IOException, "Error getting the status of the DSR line.");
return MS_RLSD_ON & dwModemStatus;
}
void
Serial::SerialImpl::readLock()
{
if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) {
THROW (IOException, "Error claiming read mutex.");
}
}
void
Serial::SerialImpl::readUnlock()
{
if (!ReleaseMutex(read_mutex)) {
THROW (IOException, "Error releasing read mutex.");
}
}
void
Serial::SerialImpl::writeLock()
{
if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) {
THROW (IOException, "Error claiming write mutex.");
}
}
void
Serial::SerialImpl::writeUnlock()
{
if (!ReleaseMutex(write_mutex)) {
THROW (IOException, "Error releasing write mutex.");
}
}

View File

@ -1,670 +0,0 @@
/* Copyright 2012 William Woodall and John Harrison */
#include "serial/impl/windows.h"
using std::string;
using std::invalid_argument;
using serial::Serial;
using serial::SerialExecption;
using serial::PortNotOpenedException;
using serial::IOException;
Serial::SerialImpl::SerialImpl (const string &port, unsigned long baudrate,
long timeout, bytesize_t bytesize,
parity_t parity, stopbits_t stopbits,
flowcontrol_t flowcontrol)
: port_ (port), fd_ (-1), isOpen_ (false), xonxoff_ (true), rtscts_ (false),
timeout_ (timeout), baudrate_ (baudrate), parity_ (parity), bytesize_ (bytesize),
stopbits_ (stopbits), flowcontrol_ (flowcontrol)
{
if (port_.empty () == false)
open ();
}
Serial::SerialImpl::~SerialImpl ()
{
close();
}
void
Serial::SerialImpl::open ()
{
if (port_.empty())
{
throw invalid_argument ("bad port specified");
}
if (isOpen_ == true)
{
throw SerialExecption ("port already open");
}
fd_ = ::open (port_.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd_ == -1)
{
switch (errno)
{
case EINTR:
// Recurse because this is a recoverable error.
open ();
return;
case ENFILE:
case EMFILE:
throw IOException ("to many file handles open");
break;
default:
throw IOException (errno);
}
}
reconfigurePort();
isOpen_ = true;
}
void
Serial::SerialImpl::reconfigurePort ()
{
if (fd_ == -1)
{
// Can only operate on a valid file descriptor
throw IOException ("invalid file descriptor");
}
struct termios options; // The options for the file descriptor
if (tcgetattr(fd_, &options) == -1)
{
throw IOException ("::tcgetattr");
}
// set up raw mode / no echo / binary
options.c_cflag |= (unsigned long) (CLOCAL|CREAD);
options.c_lflag &= (unsigned long) ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|
ISIG|IEXTEN); //|ECHOPRT
options.c_oflag &= (unsigned long) ~(OPOST);
options.c_iflag &= (unsigned long) ~(INLCR|IGNCR|ICRNL|IGNBRK);
#ifdef IUCLC
options.c_iflag &= (unsigned long) ~IUCLC;
#endif
#ifdef PARMRK
options.c_iflag &= (unsigned long) ~PARMRK;
#endif
// setup baud rate
bool custom_baud = false;
speed_t baud;
switch (baudrate_)
{
#ifdef B0
case 0: baud = B0; break;
#endif
#ifdef B50
case 50: baud = B50; break;
#endif
#ifdef B75
case 75: baud = B75; break;
#endif
#ifdef B110
case 110: baud = B110; break;
#endif
#ifdef B134
case 134: baud = B134; break;
#endif
#ifdef B150
case 150: baud = B150; break;
#endif
#ifdef B200
case 200: baud = B200; break;
#endif
#ifdef B300
case 300: baud = B300; break;
#endif
#ifdef B600
case 600: baud = B600; break;
#endif
#ifdef B1200
case 1200: baud = B1200; break;
#endif
#ifdef B1800
case 1800: baud = B1800; break;
#endif
#ifdef B2400
case 2400: baud = B2400; break;
#endif
#ifdef B4800
case 4800: baud = B4800; break;
#endif
#ifdef B7200
case 7200: baud = B7200; break;
#endif
#ifdef B9600
case 9600: baud = B9600; break;
#endif
#ifdef B14400
case 14400: baud = B14400; break;
#endif
#ifdef B19200
case 19200: baud = B19200; break;
#endif
#ifdef B28800
case 28800: baud = B28800; break;
#endif
#ifdef B57600
case 57600: baud = B57600; break;
#endif
#ifdef B76800
case 76800: baud = B76800; break;
#endif
#ifdef B38400
case 38400: baud = B38400; break;
#endif
#ifdef B115200
case 115200: baud = B115200; break;
#endif
#ifdef B128000
case 128000: baud = B128000; break;
#endif
#ifdef B153600
case 153600: baud = B153600; break;
#endif
#ifdef B230400
case 230400: baud = B230400; break;
#endif
#ifdef B256000
case 256000: baud = B256000; break;
#endif
#ifdef B460800
case 460800: baud = B460800; break;
#endif
#ifdef B921600
case 921600: baud = B921600; break;
#endif
default:
custom_baud = true;
// Mac OS X 10.x Support
#if defined(__APPLE__) && defined(__MACH__)
#define IOSSIOSPEED _IOW('T', 2, speed_t)
int new_baud = static_cast<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;
if (ioctl(fd_, TIOCSSERIAL, ser) < 0)
{
throw IOException (errno);
}
#else
throw invalid_argument ("OS does not currently support custom bauds");
#endif
}
if (custom_baud == false)
{
#ifdef _BSD_SOURCE
::cfsetspeed(&options, baud);
#else
::cfsetispeed(&options, baud);
::cfsetospeed(&options, baud);
#endif
}
// setup char len
options.c_cflag &= (unsigned long) ~CSIZE;
if (bytesize_ == EIGHTBITS)
options.c_cflag |= CS8;
else if (bytesize_ == SEVENBITS)
options.c_cflag |= CS7;
else if (bytesize_ == SIXBITS)
options.c_cflag |= CS6;
else if (bytesize_ == FIVEBITS)
options.c_cflag |= CS5;
else
throw invalid_argument ("invalid char len");
// setup stopbits
if (stopbits_ == STOPBITS_ONE)
options.c_cflag &= (unsigned long) ~(CSTOPB);
else if (stopbits_ == STOPBITS_ONE_POINT_FIVE)
options.c_cflag |= (CSTOPB); // XXX same as TWO.. there is no POSIX support for 1.5
else if (stopbits_ == STOPBITS_TWO)
options.c_cflag |= (CSTOPB);
else
throw invalid_argument ("invalid stop bit");
// setup parity
options.c_iflag &= (unsigned long) ~(INPCK|ISTRIP);
if (parity_ == PARITY_NONE)
{
options.c_cflag &= (unsigned long) ~(PARENB|PARODD);
}
else if (parity_ == PARITY_EVEN)
{
options.c_cflag &= (unsigned long) ~(PARODD);
options.c_cflag |= (PARENB);
}
else if (parity_ == PARITY_ODD)
{
options.c_cflag |= (PARENB|PARODD);
}
else
{
throw invalid_argument ("invalid parity");
}
// setup flow control
// xonxoff
#ifdef IXANY
if (xonxoff_)
options.c_iflag |= (IXON|IXOFF); //|IXANY)
else
options.c_iflag &= (unsigned long) ~(IXON|IXOFF|IXANY);
#else
if (xonxoff_)
options.c_iflag |= (IXON|IXOFF);
else
options.c_iflag &= (unsigned long) ~(IXON|IXOFF);
#endif
// rtscts
#ifdef CRTSCTS
if (rtscts_)
options.c_cflag |= (CRTSCTS);
else
options.c_cflag &= (unsigned long) ~(CRTSCTS);
#elif defined CNEW_RTSCTS
if (rtscts_)
options.c_cflag |= (CNEW_RTSCTS);
else
options.c_cflag &= (unsigned long) ~(CNEW_RTSCTS);
#else
#error "OS Support seems wrong."
#endif
options.c_cc[VMIN] = 1; // Minimum of 1 character in the buffer
options.c_cc[VTIME] = 0; // timeout on waiting for new data
// activate settings
::tcsetattr (fd_, TCSANOW, &options);
}
void
Serial::SerialImpl::close ()
{
if (isOpen_ == true)
{
if (fd_ != -1)
{
::close (fd_); // Ignoring the outcome
fd_ = -1;
}
isOpen_ = false;
}
}
bool
Serial::SerialImpl::isOpen () const
{
return isOpen_;
}
size_t
Serial::SerialImpl::available ()
{
if (!isOpen_)
{
return 0;
}
int count = 0;
int result = ioctl (fd_, TIOCINQ, &count);
if (result == 0)
{
return static_cast<size_t> (count);
}
else
{
throw IOException (errno);
}
}
size_t
Serial::SerialImpl::read (char* buf, size_t size)
{
if (!isOpen_)
{
throw PortNotOpenedException ("Serial::read");
}
fd_set readfds;
ssize_t bytes_read = 0;
int count = 0;
while (true)
{
count++;
if (timeout_ != -1)
{
FD_ZERO (&readfds);
FD_SET (fd_, &readfds);
struct timeval timeout;
timeout.tv_sec = timeout_ / 1000;
timeout.tv_usec = static_cast<int> (timeout_ % 1000) * 1000;
int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout);
if (r == -1 && errno == EINTR)
continue;
if (r == -1)
{
throw IOException (errno);
}
}
if (timeout_ == -1 || FD_ISSET (fd_, &readfds))
{
bytes_read = ::read (fd_, buf, size);
// read should always return some data as select reported it was
// ready to read when we get to this point.
if (bytes_read < 1)
{
// Disconnected devices, at least on Linux, show the
// behavior that they are always ready to read immediately
// but reading returns nothing.
throw SerialExecption ("device reports readiness to read but "
"returned no data (device disconnected?)");
}
break;
}
else
{
break;
}
}
return static_cast<size_t> (bytes_read);
}
size_t
Serial::SerialImpl::write (const string &data)
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::write");
}
fd_set writefds;
ssize_t bytes_written = 0;
while (true)
{
if (timeout_ != -1)
{
FD_ZERO (&writefds);
FD_SET (fd_, &writefds);
struct timeval timeout;
timeout.tv_sec = timeout_ / 1000;
timeout.tv_usec = static_cast<int> (timeout_ % 1000) * 1000;
int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout);
if (r == -1 && errno == EINTR)
continue;
if (r == -1)
{
throw IOException (errno);
}
}
if (timeout_ == -1 || FD_ISSET (fd_, &writefds))
{
bytes_written = ::write (fd_, data.c_str (), data.length ());
// read should always return some data as select reported it was
// ready to read when we get to this point.
if (bytes_written < 1)
{
// Disconnected devices, at least on Linux, show the
// behavior that they are always ready to read immediately
// but reading returns nothing.
throw SerialExecption ("device reports readiness to read but "
"returned no data (device disconnected?)");
}
break;
}
else
{
break;
}
}
return static_cast<size_t> (bytes_written);
}
void
Serial::SerialImpl::setPort (const string &port)
{
port_ = port;
}
string
Serial::SerialImpl::getPort () const
{
return port_;
}
void
Serial::SerialImpl::setTimeout (long timeout)
{
timeout_ = timeout;
}
long
Serial::SerialImpl::getTimeout () const
{
return timeout_;
}
void
Serial::SerialImpl::setBaudrate (unsigned long baudrate)
{
baudrate_ = baudrate;
if (isOpen_)
reconfigurePort ();
}
unsigned long
Serial::SerialImpl::getBaudrate () const
{
return baudrate_;
}
void
Serial::SerialImpl::setBytesize (serial::bytesize_t bytesize)
{
bytesize_ = bytesize;
if (isOpen_)
reconfigurePort ();
}
serial::bytesize_t
Serial::SerialImpl::getBytesize () const
{
return bytesize_;
}
void
Serial::SerialImpl::setParity (serial::parity_t parity)
{
parity_ = parity;
if (isOpen_)
reconfigurePort ();
}
serial::parity_t
Serial::SerialImpl::getParity () const
{
return parity_;
}
void
Serial::SerialImpl::setStopbits (serial::stopbits_t stopbits)
{
stopbits_ = stopbits;
if (isOpen_)
reconfigurePort ();
}
serial::stopbits_t
Serial::SerialImpl::getStopbits () const
{
return stopbits_;
}
void
Serial::SerialImpl::setFlowcontrol (serial::flowcontrol_t flowcontrol)
{
flowcontrol_ = flowcontrol;
if (isOpen_)
reconfigurePort ();
}
serial::flowcontrol_t
Serial::SerialImpl::getFlowcontrol () const
{
return flowcontrol_;
}
void
Serial::SerialImpl::flush ()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::flush");
}
tcdrain (fd_);
}
void
Serial::SerialImpl::flushInput ()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::flushInput");
}
tcflush (fd_, TCIFLUSH);
}
void
Serial::SerialImpl::flushOutput ()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::flushOutput");
}
tcflush (fd_, TCOFLUSH);
}
void
Serial::SerialImpl::sendBreak (int duration)
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::sendBreak");
}
tcsendbreak (fd_, static_cast<int> (duration/4));
}
void
Serial::SerialImpl::setBreak (bool level)
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::setBreak");
}
if (level)
{
ioctl (fd_, TIOCSBRK);
}
else {
ioctl (fd_, TIOCCBRK);
}
}
void
Serial::SerialImpl::setRTS (bool level)
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::setRTS");
}
if (level)
{
ioctl (fd_, TIOCMBIS, TIOCM_RTS);
}
else {
ioctl (fd_, TIOCMBIC, TIOCM_RTS);
}
}
void
Serial::SerialImpl::setDTR (bool level)
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::setDTR");
}
if (level)
{
ioctl (fd_, TIOCMBIS, TIOCM_DTR);
}
else
{
ioctl (fd_, TIOCMBIC, TIOCM_DTR);
}
}
bool
Serial::SerialImpl::getCTS ()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::getCTS");
}
int s = ioctl (fd_, TIOCMGET, 0);
return (s & TIOCM_CTS) != 0;
}
bool
Serial::SerialImpl::getDSR()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::getDSR");
}
int s = ioctl(fd_, TIOCMGET, 0);
return (s & TIOCM_DSR) != 0;
}
bool
Serial::SerialImpl::getRI()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::getRI");
}
int s = ioctl (fd_, TIOCMGET, 0);
return (s & TIOCM_RI) != 0;
}
bool
Serial::SerialImpl::getCD()
{
if (isOpen_ == false)
{
throw PortNotOpenedException ("Serial::getCD");
}
int s = ioctl (fd_, TIOCMGET, 0);
return (s & TIOCM_CD) != 0;
}

View File

@ -48,7 +48,7 @@ private:
SerialImpl *pimpl_; SerialImpl *pimpl_;
}; };
Serial::Serial (const string &port, unsigned long baudrate, Timeout timeout, Serial::Serial (const string &port, uint32_t baudrate, Timeout timeout,
bytesize_t bytesize, parity_t parity, stopbits_t stopbits, bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
flowcontrol_t flowcontrol) flowcontrol_t flowcontrol)
: read_cache_("") : read_cache_("")
@ -88,23 +88,23 @@ Serial::available ()
} }
size_t size_t
Serial::read_ (unsigned char *buffer, size_t size) Serial::read_ (uint8_t *buffer, size_t size)
{ {
return this->pimpl_->read (buffer, size); return this->pimpl_->read (buffer, size);
} }
size_t size_t
Serial::read (unsigned char *buffer, size_t size) Serial::read (uint8_t *buffer, size_t size)
{ {
ScopedReadLock (this->pimpl_); ScopedReadLock (this->pimpl_);
return this->pimpl_->read (buffer, size); return this->pimpl_->read (buffer, size);
} }
size_t size_t
Serial::read (std::vector<unsigned char> &buffer, size_t size) Serial::read (std::vector<uint8_t> &buffer, size_t size)
{ {
ScopedReadLock (this->pimpl_); ScopedReadLock (this->pimpl_);
unsigned char *buffer_ = new unsigned char[size]; uint8_t *buffer_ = new uint8_t[size];
size_t bytes_read = this->pimpl_->read (buffer_, size); size_t bytes_read = this->pimpl_->read (buffer_, size);
buffer.insert (buffer.end (), buffer_, buffer_+bytes_read); buffer.insert (buffer.end (), buffer_, buffer_+bytes_read);
delete[] buffer_; delete[] buffer_;
@ -115,7 +115,7 @@ size_t
Serial::read (std::string &buffer, size_t size) Serial::read (std::string &buffer, size_t size)
{ {
ScopedReadLock (this->pimpl_); ScopedReadLock (this->pimpl_);
unsigned char *buffer_ = new unsigned char[size]; uint8_t *buffer_ = new uint8_t[size];
size_t bytes_read = this->pimpl_->read (buffer_, size); size_t bytes_read = this->pimpl_->read (buffer_, size);
buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read); buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read);
delete[] buffer_; delete[] buffer_;
@ -135,8 +135,8 @@ Serial::readline (string &buffer, size_t size, string eol)
{ {
ScopedReadLock (this->pimpl_); ScopedReadLock (this->pimpl_);
size_t eol_len = eol.length (); size_t eol_len = eol.length ();
unsigned char *buffer_ = static_cast<unsigned char*> uint8_t *buffer_ = static_cast<uint8_t*>
(alloca (size * sizeof (unsigned char))); (alloca (size * sizeof (uint8_t)));
size_t read_so_far = 0; size_t read_so_far = 0;
while (true) while (true)
{ {
@ -171,8 +171,8 @@ Serial::readlines (size_t size, string eol)
ScopedReadLock (this->pimpl_); ScopedReadLock (this->pimpl_);
std::vector<std::string> lines; std::vector<std::string> lines;
size_t eol_len = eol.length (); size_t eol_len = eol.length ();
unsigned char *buffer_ = static_cast<unsigned char*> uint8_t *buffer_ = static_cast<uint8_t*>
(alloca (size * sizeof (unsigned char))); (alloca (size * sizeof (uint8_t)));
size_t read_so_far = 0; size_t read_so_far = 0;
size_t start_of_line = 0; size_t start_of_line = 0;
while (read_so_far < size) { while (read_so_far < size) {
@ -210,7 +210,28 @@ size_t
Serial::write (const string &data) Serial::write (const string &data)
{ {
ScopedWriteLock(this->pimpl_); ScopedWriteLock(this->pimpl_);
return pimpl_->write (data); return this->write_ (reinterpret_cast<const uint8_t*>(data.c_str()),
data.length());
}
size_t
Serial::write (const std::vector<uint8_t> &data)
{
ScopedWriteLock(this->pimpl_);
return this->write_ (&data[0], data.size());
}
size_t
Serial::write (const uint8_t *data, size_t size)
{
ScopedWriteLock(this->pimpl_);
return this->write_(data, size);
}
size_t
Serial::write_ (const uint8_t *data, size_t length)
{
return pimpl_->write (data, length);
} }
void void
@ -242,15 +263,15 @@ Serial::getTimeout () const {
} }
void void
Serial::setBaudrate (unsigned long baudrate) Serial::setBaudrate (uint32_t baudrate)
{ {
pimpl_->setBaudrate (baudrate); pimpl_->setBaudrate (baudrate);
} }
unsigned long uint32_t
Serial::getBaudrate () const Serial::getBaudrate () const
{ {
return pimpl_->getBaudrate (); return uint32_t(pimpl_->getBaudrate ());
} }
void void