mirror of
https://github.com/wjwwood/serial.git
synced 2026-01-22 11:44:53 +08:00
Adding initial windows support.
This commit is contained in:
parent
0a66fa991d
commit
6fac95d633
1
.gitignore
vendored
1
.gitignore
vendored
@ -23,3 +23,4 @@ patched
|
||||
wiped
|
||||
msg_gen
|
||||
srv_gen
|
||||
doc/html
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
find_path(serial_INCLUDE_DIRS serial.h /usr/include/serial
|
||||
/usr/local/include/serial "$ENV{NAMER_ROOT}")
|
||||
find_path(serial_INCLUDE_DIRS serial/serial.h /usr/include
|
||||
/usr/local/include "$ENV{NAMER_ROOT}")
|
||||
|
||||
find_library(serial_LIBRARIES serial /usr/lib /usr/local/lib
|
||||
"$ENV{NAMER_ROOT}")
|
||||
|
||||
@ -70,7 +70,7 @@ Run the example:
|
||||
|
||||
The BSD License
|
||||
|
||||
Copyright (c) 2011 William Woodall
|
||||
Copyright (c) 2012 William Woodall
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall, John Harrison
|
||||
* Copyright (c) 2012 William Woodall, John Harrison
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@ -74,10 +74,10 @@ public:
|
||||
available ();
|
||||
|
||||
size_t
|
||||
read (unsigned char *buf, size_t size = 1);
|
||||
read (uint8_t *buf, size_t size = 1);
|
||||
|
||||
size_t
|
||||
write (const string &data);
|
||||
write (const uint8_t *data, size_t length);
|
||||
|
||||
void
|
||||
flush ();
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall, John Harrison
|
||||
* Copyright (c) 2012 William Woodall, John Harrison
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@ -39,6 +39,8 @@
|
||||
|
||||
#include "serial/serial.h"
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
namespace serial {
|
||||
|
||||
using std::string;
|
||||
@ -51,7 +53,6 @@ class serial::Serial::SerialImpl {
|
||||
public:
|
||||
SerialImpl (const string &port,
|
||||
unsigned long baudrate,
|
||||
long timeout,
|
||||
bytesize_t bytesize,
|
||||
parity_t parity,
|
||||
stopbits_t stopbits,
|
||||
@ -72,10 +73,10 @@ public:
|
||||
available ();
|
||||
|
||||
size_t
|
||||
read (char* buf, size_t size = 1);
|
||||
read (uint8_t *buf, size_t size = 1);
|
||||
|
||||
size_t
|
||||
write (const string &data);
|
||||
write (const uint8_t *data, size_t length);
|
||||
|
||||
void
|
||||
flush ();
|
||||
@ -98,6 +99,9 @@ public:
|
||||
void
|
||||
setDTR (bool level);
|
||||
|
||||
bool
|
||||
waitForChange ();
|
||||
|
||||
bool
|
||||
getCTS ();
|
||||
|
||||
@ -117,9 +121,9 @@ public:
|
||||
getPort () const;
|
||||
|
||||
void
|
||||
setTimeout (long timeout);
|
||||
setTimeout (Timeout &timeout);
|
||||
|
||||
long
|
||||
Timeout
|
||||
getTimeout () const;
|
||||
|
||||
void
|
||||
@ -152,24 +156,39 @@ public:
|
||||
flowcontrol_t
|
||||
getFlowcontrol () const;
|
||||
|
||||
void
|
||||
readLock ();
|
||||
|
||||
void
|
||||
readUnlock ();
|
||||
|
||||
void
|
||||
writeLock ();
|
||||
|
||||
void
|
||||
writeUnlock ();
|
||||
|
||||
protected:
|
||||
void reconfigurePort ();
|
||||
|
||||
private:
|
||||
string port_; // Path to the file descriptor
|
||||
int fd_; // The current file descriptor
|
||||
HANDLE fd_;
|
||||
|
||||
bool isOpen_;
|
||||
bool xonxoff_;
|
||||
bool rtscts_;
|
||||
bool is_open_;
|
||||
|
||||
long timeout_; // Timeout for read operations
|
||||
Timeout timeout_; // Timeout for read operations
|
||||
unsigned long baudrate_; // Baudrate
|
||||
|
||||
parity_t parity_; // Parity
|
||||
bytesize_t bytesize_; // Size of the bytes
|
||||
stopbits_t stopbits_; // Stop Bits
|
||||
flowcontrol_t flowcontrol_; // Flow Control
|
||||
|
||||
// Mutex used to lock the read functions
|
||||
HANDLE read_mutex;
|
||||
// Mutex used to lock the write functions
|
||||
HANDLE write_mutex;
|
||||
};
|
||||
|
||||
}
|
||||
@ -8,7 +8,7 @@
|
||||
*
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 William Woodall
|
||||
* Copyright (c) 2012 William Woodall
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@ -42,6 +42,7 @@
|
||||
#include <sstream>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
|
||||
#define THROW(exceptionClass, message) throw exceptionClass(__FILE__, \
|
||||
__LINE__, (message) )
|
||||
@ -89,9 +90,9 @@ typedef enum {
|
||||
* in milliseconds.
|
||||
*/
|
||||
struct Timeout {
|
||||
Timeout (long inter_byte_timeout_=0, long read_timeout_constant_=0,
|
||||
long read_timeout_multiplier_=0, long write_timeout_constant_=0,
|
||||
long write_timeout_multiplier_=0)
|
||||
Timeout (int32_t inter_byte_timeout_=0, int32_t read_timeout_constant_=0,
|
||||
int32_t read_timeout_multiplier_=0, int32_t write_timeout_constant_=0,
|
||||
int32_t write_timeout_multiplier_=0)
|
||||
: inter_byte_timeout(inter_byte_timeout_),
|
||||
read_timeout_constant(read_timeout_constant_),
|
||||
read_timeout_multiplier(read_timeout_multiplier_),
|
||||
@ -99,19 +100,19 @@ struct Timeout {
|
||||
write_timeout_multiplier(write_timeout_multiplier_)
|
||||
{}
|
||||
/*! Number of milliseconds between bytes received to timeout on. */
|
||||
long inter_byte_timeout;
|
||||
int32_t inter_byte_timeout;
|
||||
/*! A constant number of milliseconds to wait after calling read. */
|
||||
long read_timeout_constant;
|
||||
int32_t read_timeout_constant;
|
||||
/*! A multiplier against the number of requested bytes to wait after
|
||||
* calling read.
|
||||
*/
|
||||
long read_timeout_multiplier;
|
||||
int32_t read_timeout_multiplier;
|
||||
/*! A constant number of milliseconds to wait after calling write. */
|
||||
long write_timeout_constant;
|
||||
int32_t write_timeout_constant;
|
||||
/*! A multiplier against the number of requested bytes to wait after
|
||||
* calling write.
|
||||
*/
|
||||
long write_timeout_multiplier;
|
||||
int32_t write_timeout_multiplier;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -149,7 +150,7 @@ public:
|
||||
* \throw PortNotOpenedException
|
||||
*/
|
||||
Serial (const std::string &port = "",
|
||||
unsigned long baudrate = 9600,
|
||||
uint32_t baudrate = 9600,
|
||||
Timeout timeout = Timeout(),
|
||||
bytesize_t bytesize = eightbits,
|
||||
parity_t parity = parity_none,
|
||||
@ -209,25 +210,25 @@ public:
|
||||
* occur.
|
||||
* * An exception occurred, in this case an actual exception will be thrown.
|
||||
*
|
||||
* \param buffer An unsigned char array of at least the requested size.
|
||||
* \param buffer An uint8_t array of at least the requested size.
|
||||
* \param size A size_t defining how many bytes to be read.
|
||||
*
|
||||
* \return A size_t representing the number of bytes read as a result of the
|
||||
* call to read.
|
||||
*/
|
||||
size_t
|
||||
read (unsigned char *buffer, size_t size);
|
||||
read (uint8_t *buffer, size_t size);
|
||||
|
||||
/*! Read a given amount of bytes from the serial port into a give buffer.
|
||||
*
|
||||
* \param buffer A reference to a std::vector of unsigned char.
|
||||
* \param buffer A reference to a std::vector of uint8_t.
|
||||
* \param size A size_t defining how many bytes to be read.
|
||||
*
|
||||
* \return A size_t representing the number of bytes read as a result of the
|
||||
* call to read.
|
||||
*/
|
||||
size_t
|
||||
read (std::vector<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.
|
||||
*
|
||||
@ -301,7 +302,7 @@ public:
|
||||
* the serial port.
|
||||
*/
|
||||
size_t
|
||||
write (const unsigned char *data, size_t size);
|
||||
write (const uint8_t *data, size_t size);
|
||||
|
||||
/*! Write a string to the serial port.
|
||||
*
|
||||
@ -312,7 +313,7 @@ public:
|
||||
* the serial port.
|
||||
*/
|
||||
size_t
|
||||
write (const std::vector<unsigned char> &data);
|
||||
write (const std::vector<uint8_t> &data);
|
||||
|
||||
/*! Write a string to the serial port.
|
||||
*
|
||||
@ -384,9 +385,9 @@ public:
|
||||
|
||||
/*! Sets the timeout for reads and writes. */
|
||||
void
|
||||
setTimeout (long inter_byte_timeout, long read_timeout_constant,
|
||||
long read_timeout_multiplier, long write_timeout_constant,
|
||||
long write_timeout_multiplier)
|
||||
setTimeout (int32_t inter_byte_timeout, int32_t read_timeout_constant,
|
||||
int32_t read_timeout_multiplier, int32_t write_timeout_constant,
|
||||
int32_t write_timeout_multiplier)
|
||||
{
|
||||
Timeout timeout(inter_byte_timeout, read_timeout_constant,
|
||||
read_timeout_multiplier, write_timeout_constant,
|
||||
@ -417,7 +418,7 @@ public:
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
void
|
||||
setBaudrate (unsigned long baudrate);
|
||||
setBaudrate (uint32_t baudrate);
|
||||
|
||||
/*! Gets the baudrate for the serial port.
|
||||
*
|
||||
@ -427,7 +428,7 @@ public:
|
||||
*
|
||||
* \throw InvalidConfigurationException
|
||||
*/
|
||||
unsigned long
|
||||
uint32_t
|
||||
getBaudrate () const;
|
||||
|
||||
/*! Sets the bytesize for the serial port.
|
||||
@ -587,7 +588,10 @@ private:
|
||||
|
||||
// Read common function
|
||||
size_t
|
||||
read_ (unsigned char *buffer, size_t size);
|
||||
read_ (uint8_t *buffer, size_t size);
|
||||
// Write common function
|
||||
size_t
|
||||
write_ (const uint8_t *data, size_t length);
|
||||
|
||||
};
|
||||
|
||||
@ -646,11 +650,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SerialExceptionBase : public std::exception
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
} // namespace serial
|
||||
|
||||
#endif
|
||||
|
||||
@ -3,6 +3,46 @@
|
||||
{
|
||||
"selected_items":
|
||||
[
|
||||
[
|
||||
"baudr",
|
||||
"baudrate_"
|
||||
],
|
||||
[
|
||||
"dcb",
|
||||
"dcbSerialParams"
|
||||
],
|
||||
[
|
||||
"byte",
|
||||
"bytes_written size_t"
|
||||
],
|
||||
[
|
||||
"write",
|
||||
"write_timeout_multiplier int32_t"
|
||||
],
|
||||
[
|
||||
"read",
|
||||
"read_timeout_multiplier"
|
||||
],
|
||||
[
|
||||
"read_",
|
||||
"read_timeout_multiplier"
|
||||
],
|
||||
[
|
||||
"inter",
|
||||
"inter_byte_timeout"
|
||||
],
|
||||
[
|
||||
"write_",
|
||||
"write_timeout_constant"
|
||||
],
|
||||
[
|
||||
"string",
|
||||
"stringstream"
|
||||
],
|
||||
[
|
||||
"Seri",
|
||||
"SerialExecption"
|
||||
],
|
||||
[
|
||||
"tour",
|
||||
"toupper(int _c) int"
|
||||
@ -275,41 +315,25 @@
|
||||
},
|
||||
"buffers":
|
||||
[
|
||||
{
|
||||
"file": "include/serial/serial.h",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 17876,
|
||||
"line_ending": "Unix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "src/serial.cc",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 7015,
|
||||
"line_ending": "Unix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"file": "src/impl/unix.cc",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 16696,
|
||||
"line_ending": "Unix"
|
||||
}
|
||||
}
|
||||
],
|
||||
"build_system": "Packages/Python/Python.sublime-build",
|
||||
"command_palette":
|
||||
{
|
||||
"height": 47.0,
|
||||
"height": 87.0,
|
||||
"selected_items":
|
||||
[
|
||||
[
|
||||
"convert sp",
|
||||
"Indentation: Convert to Spaces"
|
||||
],
|
||||
[
|
||||
"install",
|
||||
"Package Control: Install Package"
|
||||
],
|
||||
[
|
||||
"Package Control: remo",
|
||||
"Package Control: Remove Package"
|
||||
],
|
||||
[
|
||||
"late",
|
||||
"LaTeXTools: View PDF"
|
||||
@ -332,6 +356,27 @@
|
||||
},
|
||||
"file_history":
|
||||
[
|
||||
"/Users/william/devel/serial/include/serial/serial.h",
|
||||
"/Users/william/devel/serial/include/serial/impl/win.h",
|
||||
"/Users/william/devel/serial/src/impl/win.cc",
|
||||
"/Users/william/devel/serial/src/impl/unix.cc",
|
||||
"/Users/william/devel/serial/include/serial/impl/unix.h",
|
||||
"/Users/william/devel/serial/src/serial.cc",
|
||||
"/Users/william/devel/serial/Findserial.cmake",
|
||||
"/Users/william/devel/serial/src/impl/windows.cc",
|
||||
"/Users/william/devel/serial/serial.sublime-project",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/User/SublimeClang.sublime-settings",
|
||||
"/Users/william/devel/serial/README.md",
|
||||
"/Users/william/devel/serial/doc/html/serial_8h.html",
|
||||
"/Users/william/devel/serial/doc/html/unix_8h.html",
|
||||
"/Users/william/devel/serial/doc/html/windows_8h.html",
|
||||
"/Users/william/devel/serial/include/serial/impl/windows.h",
|
||||
"/Users/william/devel/serial/doc/Doxyfile",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/Terminal/Default (OSX).sublime-keymap",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/SublimeAStyleFormatter.sublime-settings",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/Default.sublime-keymap",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeAStyleFormatter/Default (OSX).sublime-keymap",
|
||||
"/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_path_planner.py",
|
||||
"/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_coverage_planner.py",
|
||||
"/Users/william/devel/automow_ws/au_automow_common/automow_planning/tests/test_costmap.py",
|
||||
@ -343,7 +388,6 @@
|
||||
"/Users/william/devel/xbow400/src/xbow_400.cpp",
|
||||
"/Users/william/devel/xbow400/README",
|
||||
"/Users/william/devel/xbow400/xbow400.sublime-project",
|
||||
"/Users/william/Library/Application Support/Sublime Text 2/Packages/SublimeClang/SublimeClang.sublime-settings",
|
||||
"/Users/william/devel/comp6400/homework6/homework6.sublime-project",
|
||||
"/Users/william/devel/comp6400/homework6/src/main.cc",
|
||||
"/Users/william/devel/comp6400/homework6/models/student.obj",
|
||||
@ -405,9 +449,10 @@
|
||||
},
|
||||
"find_in_files":
|
||||
{
|
||||
"height": 0.0,
|
||||
"height": 93.0,
|
||||
"where_history":
|
||||
[
|
||||
"<open files>",
|
||||
""
|
||||
]
|
||||
},
|
||||
@ -416,6 +461,18 @@
|
||||
"case_sensitive": false,
|
||||
"find_history":
|
||||
[
|
||||
"flowcon",
|
||||
"xonxoff_",
|
||||
"rtscts_",
|
||||
"#ifdef B",
|
||||
"baud = B",
|
||||
"write",
|
||||
"char",
|
||||
"unsigned char",
|
||||
"char",
|
||||
"long",
|
||||
"2011",
|
||||
" *",
|
||||
"cts",
|
||||
" ",
|
||||
"o ",
|
||||
@ -444,6 +501,10 @@
|
||||
"regex": false,
|
||||
"replace_history":
|
||||
[
|
||||
"#ifdef CBR_",
|
||||
"dcbSerialParams.BaudRate = CBR_",
|
||||
"2012",
|
||||
" *",
|
||||
", ",
|
||||
"min.z",
|
||||
"min.y",
|
||||
@ -462,95 +523,8 @@
|
||||
"groups":
|
||||
[
|
||||
{
|
||||
"selected": 2,
|
||||
"sheets":
|
||||
[
|
||||
{
|
||||
"buffer": 0,
|
||||
"file": "include/serial/serial.h",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 17876,
|
||||
"regions":
|
||||
{
|
||||
},
|
||||
"selection":
|
||||
[
|
||||
[
|
||||
11407,
|
||||
11407
|
||||
]
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"syntax": "Packages/C++/C++.tmLanguage",
|
||||
"tab_size": 4,
|
||||
"translate_tabs_to_spaces": true,
|
||||
"word_wrap": true,
|
||||
"wrap_width": 80
|
||||
},
|
||||
"translation.x": 0.0,
|
||||
"translation.y": 6934.0,
|
||||
"zoom_level": 1.0
|
||||
},
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"buffer": 1,
|
||||
"file": "src/serial.cc",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 7015,
|
||||
"regions":
|
||||
{
|
||||
},
|
||||
"selection":
|
||||
[
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"syntax": "Packages/C++/C++.tmLanguage",
|
||||
"tab_size": 2,
|
||||
"translate_tabs_to_spaces": true
|
||||
},
|
||||
"translation.x": 0.0,
|
||||
"translation.y": 479.0,
|
||||
"zoom_level": 1.0
|
||||
},
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"buffer": 2,
|
||||
"file": "src/impl/unix.cc",
|
||||
"settings":
|
||||
{
|
||||
"buffer_size": 16696,
|
||||
"regions":
|
||||
{
|
||||
},
|
||||
"selection":
|
||||
[
|
||||
[
|
||||
15521,
|
||||
15521
|
||||
]
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"syntax": "Packages/C++/C++.tmLanguage",
|
||||
"tab_size": 2,
|
||||
"translate_tabs_to_spaces": true
|
||||
},
|
||||
"translation.x": 0.0,
|
||||
"translation.y": 10013.0,
|
||||
"zoom_level": 1.0
|
||||
},
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -587,7 +561,7 @@
|
||||
"cols":
|
||||
[
|
||||
0.0,
|
||||
0.61784814072,
|
||||
0.71805886817,
|
||||
1.0
|
||||
],
|
||||
"rows":
|
||||
|
||||
@ -369,7 +369,7 @@ inline void get_time_now(struct timespec &time)
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::read (unsigned char *buf, size_t size)
|
||||
Serial::SerialImpl::read (uint8_t *buf, size_t size)
|
||||
{
|
||||
if (!is_open_) {
|
||||
throw PortNotOpenedException ("Serial::read");
|
||||
@ -470,12 +470,104 @@ Serial::SerialImpl::read (unsigned char *buf, size_t size)
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::SerialImpl::write (const string &data)
|
||||
Serial::SerialImpl::write (const uint8_t *data, size_t length)
|
||||
{
|
||||
if (is_open_ == false) {
|
||||
throw PortNotOpenedException ("Serial::write");
|
||||
}
|
||||
return static_cast<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
|
||||
|
||||
549
src/impl/win.cc
Normal file
549
src/impl/win.cc
Normal 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.");
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ private:
|
||||
SerialImpl *pimpl_;
|
||||
};
|
||||
|
||||
Serial::Serial (const string &port, unsigned long baudrate, Timeout timeout,
|
||||
Serial::Serial (const string &port, uint32_t baudrate, Timeout timeout,
|
||||
bytesize_t bytesize, parity_t parity, stopbits_t stopbits,
|
||||
flowcontrol_t flowcontrol)
|
||||
: read_cache_("")
|
||||
@ -88,23 +88,23 @@ Serial::available ()
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::read_ (unsigned char *buffer, size_t size)
|
||||
Serial::read_ (uint8_t *buffer, size_t size)
|
||||
{
|
||||
return this->pimpl_->read (buffer, size);
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::read (unsigned char *buffer, size_t size)
|
||||
Serial::read (uint8_t *buffer, size_t size)
|
||||
{
|
||||
ScopedReadLock (this->pimpl_);
|
||||
return this->pimpl_->read (buffer, size);
|
||||
}
|
||||
|
||||
size_t
|
||||
Serial::read (std::vector<unsigned char> &buffer, size_t size)
|
||||
Serial::read (std::vector<uint8_t> &buffer, size_t size)
|
||||
{
|
||||
ScopedReadLock (this->pimpl_);
|
||||
unsigned char *buffer_ = new unsigned char[size];
|
||||
uint8_t *buffer_ = new uint8_t[size];
|
||||
size_t bytes_read = this->pimpl_->read (buffer_, size);
|
||||
buffer.insert (buffer.end (), buffer_, buffer_+bytes_read);
|
||||
delete[] buffer_;
|
||||
@ -115,7 +115,7 @@ size_t
|
||||
Serial::read (std::string &buffer, size_t size)
|
||||
{
|
||||
ScopedReadLock (this->pimpl_);
|
||||
unsigned char *buffer_ = new unsigned char[size];
|
||||
uint8_t *buffer_ = new uint8_t[size];
|
||||
size_t bytes_read = this->pimpl_->read (buffer_, size);
|
||||
buffer.append (reinterpret_cast<const char*>(buffer_), bytes_read);
|
||||
delete[] buffer_;
|
||||
@ -135,8 +135,8 @@ Serial::readline (string &buffer, size_t size, string eol)
|
||||
{
|
||||
ScopedReadLock (this->pimpl_);
|
||||
size_t eol_len = eol.length ();
|
||||
unsigned char *buffer_ = static_cast<unsigned char*>
|
||||
(alloca (size * sizeof (unsigned char)));
|
||||
uint8_t *buffer_ = static_cast<uint8_t*>
|
||||
(alloca (size * sizeof (uint8_t)));
|
||||
size_t read_so_far = 0;
|
||||
while (true)
|
||||
{
|
||||
@ -171,8 +171,8 @@ Serial::readlines (size_t size, string eol)
|
||||
ScopedReadLock (this->pimpl_);
|
||||
std::vector<std::string> lines;
|
||||
size_t eol_len = eol.length ();
|
||||
unsigned char *buffer_ = static_cast<unsigned char*>
|
||||
(alloca (size * sizeof (unsigned char)));
|
||||
uint8_t *buffer_ = static_cast<uint8_t*>
|
||||
(alloca (size * sizeof (uint8_t)));
|
||||
size_t read_so_far = 0;
|
||||
size_t start_of_line = 0;
|
||||
while (read_so_far < size) {
|
||||
@ -210,7 +210,28 @@ size_t
|
||||
Serial::write (const string &data)
|
||||
{
|
||||
ScopedWriteLock(this->pimpl_);
|
||||
return pimpl_->write (data);
|
||||
return this->write_ (reinterpret_cast<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
|
||||
@ -242,15 +263,15 @@ Serial::getTimeout () const {
|
||||
}
|
||||
|
||||
void
|
||||
Serial::setBaudrate (unsigned long baudrate)
|
||||
Serial::setBaudrate (uint32_t baudrate)
|
||||
{
|
||||
pimpl_->setBaudrate (baudrate);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
uint32_t
|
||||
Serial::getBaudrate () const
|
||||
{
|
||||
return pimpl_->getBaudrate ();
|
||||
return uint32_t(pimpl_->getBaudrate ());
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user