diff --git a/examples/serial_example.cc b/examples/serial_example.cc index 35c4a74..27857ff 100644 --- a/examples/serial_example.cc +++ b/examples/serial_example.cc @@ -1,5 +1,6 @@ #include #include +#include #include @@ -7,14 +8,17 @@ int run(int argc, char **argv) { - if(argc < 2) { - std::cerr << "Usage: test_serial " << std::endl; + if(argc < 3) { + std::cerr << "Usage: test_serial " << std::endl; return 0; } std::string port(argv[1]); - + unsigned long baud = 0; + + sscanf(argv[2], "%lu", &baud); + // port, baudrate, timeout in milliseconds - serial::Serial serial(port, 115200, 250); + serial::Serial serial(port, baud, 250); std::cout << "Is the serial port open?"; if(serial.isOpen()) diff --git a/include/serial/serial.h b/include/serial/serial.h index fa21c72..e924abc 100644 --- a/include/serial/serial.h +++ b/include/serial/serial.h @@ -83,39 +83,53 @@ typedef enum { FLOWCONTROL_HARDWARE } flowcontrol_t; -class SerialExecption : public std::exception { - const char * e_what; +class SerialExecption : public std::exception +{ + const char* e_what_; public: - SerialExecption(const char *description) {e_what=description;}; - virtual const char* what() const throw() { - std::stringstream ss; - ss << "SerialException " << this->e_what << " failed."; - return ss.str().c_str(); + SerialExecption (const char *description) : e_what_ (description) {} + + virtual const char* what () const throw () + { + std::stringstream ss; + ss << "SerialException " << e_what_ << " failed."; + return ss.str ().c_str (); } }; -class IOException : public std::exception { - const char * e_what; +class IOException : public std::exception +{ + const char* e_what_; + int errno_; public: - IOException(const char * description) {e_what = description;} + explicit IOException (int errnum) : e_what_ (strerror (errnum)), errno_(errnum) {} + explicit IOException (const char * description) : e_what_ (description), errno_(0) {} - virtual const char* what() const throw() { - std::stringstream ss; - ss << "IO Exception " << this->e_what << " failed."; - return ss.str().c_str(); - } + int getErrorNumber () { return errno_; } + + virtual const char* what () const throw () + { + std::stringstream ss; + if (errno_ == 0) + ss << "IO Exception " << e_what_ << " failed."; + else + ss << "IO Exception " << errno_ << ":" << e_what_ << " failed."; + return ss.str ().c_str (); + } }; -class PortNotOpenedException : public std::exception { - const char * e_what; +class PortNotOpenedException : public std::exception +{ + const char * e_what_; public: - PortNotOpenedException(const char * description) {e_what = description;} + PortNotOpenedException (const char * description) : e_what_ (description) {} - virtual const char* what() const throw() { + virtual const char* what () const throw () + { std::stringstream ss; - ss << e_what << " called before port was opened."; - return ss.str().c_str(); - } + ss << e_what_ << " called before port was opened."; + return ss.str ().c_str (); + } }; diff --git a/src/impl/unix.cc b/src/impl/unix.cc index b598024..24ad257 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -64,7 +64,19 @@ Serial::SerialImpl::open () if (fd_ == -1) { - throw IOException ("invalid file descriptor"); + 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(); @@ -215,7 +227,7 @@ Serial::SerialImpl::available () } else { - throw IOException ("ioctl"); + throw IOException (errno); } } @@ -244,8 +256,7 @@ Serial::SerialImpl::read (char* buf, size_t size) if (r == -1) { - perror("select()"); - exit(EXIT_FAILURE); + throw IOException (errno); } } @@ -276,12 +287,27 @@ Serial::SerialImpl::read (char* buf, size_t size) size_t Serial::SerialImpl::write (const string &data) { - if (isOpen_ == false) { + if (isOpen_ == false) + { throw PortNotOpenedException ("Serial::write"); } + ssize_t n = ::write (fd_, data.c_str (), data.length ()); - if (n == -1) { - throw IOException ("Write"); + + if (n != static_cast (data.length ())) + { + throw IOException ("Write did not complete"); + } + else if (n == -1) + { + if (errno == EINTR) + { + return write (data); + } + else + { + throw IOException (errno); + } } return static_cast (n); } diff --git a/src/serial.cc b/src/serial.cc index a024538..c8ac752 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -167,7 +167,7 @@ Serial::readlines(string eol) { if (pimpl_->getTimeout () < 0) { - throw "Error, must be set for readlines"; + throw invalid_argument ("Error, must be set for readlines"); } size_t leneol = eol.length (); vector lines; @@ -339,3 +339,4 @@ bool Serial::getCD () { return pimpl_->getCD (); } + diff --git a/tests/proof_of_concepts/python_serial_test.py b/tests/proof_of_concepts/python_serial_test.py new file mode 100644 index 0000000..6f92b84 --- /dev/null +++ b/tests/proof_of_concepts/python_serial_test.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import serial, sys + +if len(sys.argv) != 2: + print "python: Usage_serial_test " + sys.exit(1) + +sio = serial.Serial(sys.argv[1], 115200) +sio.timeout = 250 + +while True: + sio.write("Testing.") + print sio.read(8) +