From 9b0fdfc2f57d514b2766f31a693a5ae9dc9d3a62 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 23 Jan 2012 16:17:57 -0600 Subject: [PATCH] Validate bauds and add the ability to set custom bauds. --- src/impl/unix.cc | 133 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 6 deletions(-) diff --git a/src/impl/unix.cc b/src/impl/unix.cc index 207eaf0..394ad05 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -31,6 +31,7 @@ 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, @@ -114,8 +115,131 @@ Serial::SerialImpl::reconfigurePort () #endif // setup baud rate - // TODO(ash_git): validate baud rate - cfsetspeed(&options, baudrate_); + 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 (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, buf) < 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; @@ -333,10 +457,7 @@ Serial::SerialImpl::write (const string &data) break; } } - if (bytes_written != static_cast (data.length ())) - { - throw IOException ("Write did not complete"); - } + return static_cast (bytes_written); }