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

Merge branch 'new_api' of github.com:wjwwood/serial into new_api

Conflicts:
	.gitignore
This commit is contained in:
William Woodall 2012-06-06 18:58:51 -05:00
commit 520ccb54f4
5 changed files with 64 additions and 28 deletions

1
.gitignore vendored
View File

@ -24,3 +24,4 @@ wiped
msg_gen msg_gen
srv_gen srv_gen
doc/html doc/html
*sublime-workspace

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.4.6)
set(ROS_ROOT $ENV{ROS_ROOT}) set(ROS_ROOT $ENV{ROS_ROOT})
option(SERIAL_BUILD_WIHOUT_ROS "Build without ROS?" OFF) option(SERIAL_BUILD_WIHOUT_ROS "Build without ROS?" ON)
if(DEFINED ROS_ROOT AND NOT SERIAL_BUILD_WIHOUT_ROS) if(DEFINED ROS_ROOT AND NOT SERIAL_BUILD_WIHOUT_ROS)
# Build with ROS # Build with ROS

View File

@ -39,6 +39,7 @@
#include <limits> #include <limits>
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstring>
#include <sstream> #include <sstream>
#include <exception> #include <exception>
#include <stdexcept> #include <stdexcept>
@ -99,6 +100,20 @@ struct Timeout {
write_timeout_constant(write_timeout_constant_), write_timeout_constant(write_timeout_constant_),
write_timeout_multiplier(write_timeout_multiplier_) write_timeout_multiplier(write_timeout_multiplier_)
{} {}
/*!
* Convenience function to generate Timeout structs using a
* single absolute timeout.
*
* \param timeout A long that defines the time in milliseconds until a
* timeout occurs after a call to read or write is made.
*
* \return Timeout struct that represents this simple timeout provided.
*/
static Timeout simpleTimeout(long timeout) {
return Timeout(0, timeout, 0, timeout, 0);
}
/*! Number of milliseconds between bytes received to timeout on. */ /*! Number of milliseconds between bytes received to timeout on. */
int32_t 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. */

View File

@ -1,4 +1,6 @@
{ {
"word_wrap": "on",
"wrap_width": 80,
"folders": "folders":
[ [
{ {

View File

@ -371,47 +371,65 @@ inline void get_time_now(struct timespec &time)
size_t size_t
Serial::SerialImpl::read (uint8_t *buf, size_t size) Serial::SerialImpl::read (uint8_t *buf, size_t size)
{ {
// If the port is not open, throw
if (!is_open_) { if (!is_open_) {
throw PortNotOpenedException ("Serial::read"); throw PortNotOpenedException ("Serial::read");
} }
fd_set readfds; fd_set readfds;
size_t bytes_read = 0; size_t bytes_read = 0;
struct timeval timeout; // Setup the total_timeout timeval
timeout.tv_sec = timeout_.read_timeout_constant / 1000; // This timeout is maximum time before a timeout after read is called
timeout.tv_usec = static_cast<int> (timeout_.read_timeout_constant % 1000); struct timeval total_timeout;
timeout.tv_usec *= 1000; // To convert to micro seconds // Calculate total timeout in milliseconds t_c + (t_m * N)
long total_timeout_ms = timeout_.read_timeout_constant;
total_timeout_ms += timeout_.read_timeout_multiplier*static_cast<long>(size);
total_timeout.tv_sec = total_timeout_ms / 1000;
total_timeout.tv_usec = static_cast<int>(total_timeout_ms % 1000);
total_timeout.tv_usec *= 1000; // To convert to micro seconds
// Setup the inter byte timeout
struct timeval inter_byte_timeout;
inter_byte_timeout.tv_sec = timeout_.inter_byte_timeout / 1000;
inter_byte_timeout.tv_usec =
static_cast<int> (timeout_.inter_byte_timeout % 1000);
inter_byte_timeout.tv_usec *= 1000; // To convert to micro seconds
while (bytes_read < size) { while (bytes_read < size) {
// Setup the select timeout timeval
struct timeval timeout;
// If the total_timeout is less than the inter_byte_timeout
if (total_timeout.tv_sec < inter_byte_timeout.tv_sec
|| (total_timeout.tv_sec == inter_byte_timeout.tv_sec
&& total_timeout.tv_usec < inter_byte_timeout.tv_sec))
{
// Then set the select timeout to use the total time
timeout = total_timeout;
} else {
// Else set the select timeout to use the inter byte time
timeout = inter_byte_timeout;
}
FD_ZERO (&readfds); FD_ZERO (&readfds);
FD_SET (fd_, &readfds); FD_SET (fd_, &readfds);
// On Linux the timeout struct is updated by select to contain the time
// left on the timeout to make looping easier, but on other platforms this
// does not occur.
#if !defined(__linux__)
// Begin timing select // Begin timing select
struct timespec start, end; struct timespec start, end;
get_time_now(start); get_time_now (start);
#endif // Call select to block for serial data or a timeout
// Do the select
int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout); int r = select (fd_ + 1, &readfds, NULL, NULL, &timeout);
#if !defined(__linux__)
// Calculate difference and update the structure // Calculate difference and update the structure
get_time_now(end); get_time_now (end);
// Calculate the time select took // Calculate the time select took
struct timeval diff; struct timeval diff;
diff.tv_sec = end.tv_sec - start.tv_sec; diff.tv_sec = end.tv_sec - start.tv_sec;
diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000); diff.tv_usec = static_cast<int> ((end.tv_nsec - start.tv_nsec) / 1000);
// Update the timeout // Update the timeout
if (timeout.tv_sec <= diff.tv_sec) { if (total_timeout.tv_sec <= diff.tv_sec) {
timeout.tv_sec = 0; total_timeout.tv_sec = 0;
} else { } else {
timeout.tv_sec -= diff.tv_sec; total_timeout.tv_sec -= diff.tv_sec;
} }
if (timeout.tv_usec <= diff.tv_usec) { if (total_timeout.tv_usec <= diff.tv_usec) {
timeout.tv_usec = 0; total_timeout.tv_usec = 0;
} else { } else {
timeout.tv_usec -= diff.tv_usec; total_timeout.tv_usec -= diff.tv_usec;
} }
#endif
// Figure out what happened by looking at select's response 'r' // Figure out what happened by looking at select's response 'r'
/** Error **/ /** Error **/
@ -431,7 +449,7 @@ Serial::SerialImpl::read (uint8_t *buf, size_t size)
if (r > 0) { if (r > 0) {
// Make sure our file descriptor is in the ready to read list // Make sure our file descriptor is in the ready to read list
if (FD_ISSET (fd_, &readfds)) { if (FD_ISSET (fd_, &readfds)) {
// This should be non-blocking returning only what is avaialble now // This should be non-blocking returning only what is available now
// Then returning so that select can block again. // Then returning so that select can block again.
ssize_t bytes_read_now = ssize_t bytes_read_now =
::read (fd_, buf + bytes_read, size - bytes_read); ::read (fd_, buf + bytes_read, size - bytes_read);
@ -785,7 +803,7 @@ Serial::SerialImpl::getDSR ()
} }
bool bool
Serial::SerialImpl::getRI() Serial::SerialImpl::getRI ()
{ {
if (is_open_ == false) { if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getRI"); throw PortNotOpenedException ("Serial::getRI");
@ -795,7 +813,7 @@ Serial::SerialImpl::getRI()
} }
bool bool
Serial::SerialImpl::getCD() Serial::SerialImpl::getCD ()
{ {
if (is_open_ == false) { if (is_open_ == false) {
throw PortNotOpenedException ("Serial::getCD"); throw PortNotOpenedException ("Serial::getCD");
@ -805,7 +823,7 @@ Serial::SerialImpl::getCD()
} }
void void
Serial::SerialImpl::readLock() Serial::SerialImpl::readLock ()
{ {
int result = pthread_mutex_lock(&this->read_mutex); int result = pthread_mutex_lock(&this->read_mutex);
if (result) { if (result) {
@ -814,7 +832,7 @@ Serial::SerialImpl::readLock()
} }
void void
Serial::SerialImpl::readUnlock() Serial::SerialImpl::readUnlock ()
{ {
int result = pthread_mutex_unlock(&this->read_mutex); int result = pthread_mutex_unlock(&this->read_mutex);
if (result) { if (result) {
@ -823,7 +841,7 @@ Serial::SerialImpl::readUnlock()
} }
void void
Serial::SerialImpl::writeLock() Serial::SerialImpl::writeLock ()
{ {
int result = pthread_mutex_lock(&this->write_mutex); int result = pthread_mutex_lock(&this->write_mutex);
if (result) { if (result) {
@ -832,7 +850,7 @@ Serial::SerialImpl::writeLock()
} }
void void
Serial::SerialImpl::writeUnlock() Serial::SerialImpl::writeUnlock ()
{ {
int result = pthread_mutex_unlock(&this->write_mutex); int result = pthread_mutex_unlock(&this->write_mutex);
if (result) { if (result) {