11 using std::stringstream;
 
   12 using std::invalid_argument;
 
   24 _prefix_port_if_needed(
const wstring &input)
 
   26   static wstring windows_com_port_prefix = L
"\\\\.\\";
 
   27   if (input.compare(windows_com_port_prefix) != 0)
 
   29     return windows_com_port_prefix + input;
 
   33 Serial::SerialImpl::SerialImpl (
const string &port, 
unsigned long baudrate,
 
   37   : port_ (port.begin(), port.end()), fd_ (INVALID_HANDLE_VALUE), is_open_ (false),
 
   38     baudrate_ (baudrate), parity_ (parity),
 
   39     bytesize_ (bytesize), stopbits_ (stopbits), flowcontrol_ (flowcontrol)
 
   41   read_mutex = CreateMutex(NULL, 
false, NULL);
 
   42   write_mutex = CreateMutex(NULL, 
false, NULL);
 
   43   if (port_.empty () == 
false)
 
   47 Serial::SerialImpl::~SerialImpl ()
 
   50   CloseHandle(read_mutex);
 
   51   CloseHandle(write_mutex);
 
   55 Serial::SerialImpl::open ()
 
   58     throw invalid_argument (
"Empty port is invalid.");
 
   60   if (is_open_ == 
true) {
 
   61     throw SerialException (
"Serial port already open.");
 
   65   wstring port_with_prefix = _prefix_port_if_needed(port_);
 
   66   LPCWSTR lp_port = port_with_prefix.c_str();
 
   67   fd_ = CreateFileW(lp_port,
 
   68                     GENERIC_READ | GENERIC_WRITE,
 
   72                     FILE_ATTRIBUTE_NORMAL,
 
   75   if (fd_ == INVALID_HANDLE_VALUE) {
 
   76     DWORD errno_ = GetLastError();
 
   79     case ERROR_FILE_NOT_FOUND:
 
   81       ss << 
"Specified port, " << this->
getPort() << 
", does not exist.";
 
   82       THROW (IOException, ss.str().c_str());
 
   84       ss << 
"Unknown error opening the serial port: " << errno;
 
   85       THROW (IOException, ss.str().c_str());
 
   94 Serial::SerialImpl::reconfigurePort ()
 
   96   if (fd_ == INVALID_HANDLE_VALUE) {
 
   98     THROW (IOException, 
"Invalid file descriptor, is the serial port open?");
 
  101   DCB dcbSerialParams = {0};
 
  103   dcbSerialParams.DCBlength=
sizeof(dcbSerialParams);
 
  105   if (!GetCommState(fd_, &dcbSerialParams)) {
 
  107     THROW (IOException, 
"Error getting the serial port state.");
 
  113   case 0: dcbSerialParams.BaudRate = CBR_0; 
break;
 
  116   case 50: dcbSerialParams.BaudRate = CBR_50; 
break;
 
  119   case 75: dcbSerialParams.BaudRate = CBR_75; 
break;
 
  122   case 110: dcbSerialParams.BaudRate = CBR_110; 
break;
 
  125   case 134: dcbSerialParams.BaudRate = CBR_134; 
break;
 
  128   case 150: dcbSerialParams.BaudRate = CBR_150; 
break;
 
  131   case 200: dcbSerialParams.BaudRate = CBR_200; 
break;
 
  134   case 300: dcbSerialParams.BaudRate = CBR_300; 
break;
 
  137   case 600: dcbSerialParams.BaudRate = CBR_600; 
break;
 
  140   case 1200: dcbSerialParams.BaudRate = CBR_1200; 
break;
 
  143   case 1800: dcbSerialParams.BaudRate = CBR_1800; 
break;
 
  146   case 2400: dcbSerialParams.BaudRate = CBR_2400; 
break;
 
  149   case 4800: dcbSerialParams.BaudRate = CBR_4800; 
break;
 
  152   case 7200: dcbSerialParams.BaudRate = CBR_7200; 
break;
 
  155   case 9600: dcbSerialParams.BaudRate = CBR_9600; 
break;
 
  158   case 14400: dcbSerialParams.BaudRate = CBR_14400; 
break;
 
  161   case 19200: dcbSerialParams.BaudRate = CBR_19200; 
break;
 
  164   case 28800: dcbSerialParams.BaudRate = CBR_28800; 
break;
 
  167   case 57600: dcbSerialParams.BaudRate = CBR_57600; 
break;
 
  170   case 76800: dcbSerialParams.BaudRate = CBR_76800; 
break;
 
  173   case 38400: dcbSerialParams.BaudRate = CBR_38400; 
break;
 
  176   case 115200: dcbSerialParams.BaudRate = CBR_115200; 
break;
 
  179   case 128000: dcbSerialParams.BaudRate = CBR_128000; 
break;
 
  182   case 153600: dcbSerialParams.BaudRate = CBR_153600; 
break;
 
  185   case 230400: dcbSerialParams.BaudRate = CBR_230400; 
break;
 
  188   case 256000: dcbSerialParams.BaudRate = CBR_256000; 
break;
 
  191   case 460800: dcbSerialParams.BaudRate = CBR_460800; 
break;
 
  194   case 921600: dcbSerialParams.BaudRate = CBR_921600; 
break;
 
  198     dcbSerialParams.BaudRate = baudrate_;
 
  203     dcbSerialParams.ByteSize = 8;
 
  205     dcbSerialParams.ByteSize = 7;
 
  207     dcbSerialParams.ByteSize = 6;
 
  209     dcbSerialParams.ByteSize = 5;
 
  211     throw invalid_argument (
"invalid char len");
 
  215     dcbSerialParams.StopBits = ONESTOPBIT;
 
  217     dcbSerialParams.StopBits = ONE5STOPBITS;
 
  219     dcbSerialParams.StopBits = TWOSTOPBITS;
 
  221     throw invalid_argument (
"invalid stop bit");
 
  225     dcbSerialParams.Parity = NOPARITY;
 
  227     dcbSerialParams.Parity = EVENPARITY;
 
  229     dcbSerialParams.Parity = ODDPARITY;
 
  231     dcbSerialParams.Parity = MARKPARITY;
 
  233     dcbSerialParams.Parity = SPACEPARITY;
 
  235     throw invalid_argument (
"invalid parity");
 
  240     dcbSerialParams.fOutxCtsFlow = 
false;
 
  241     dcbSerialParams.fRtsControl = 0x00;
 
  242     dcbSerialParams.fOutX = 
false;
 
  243     dcbSerialParams.fInX = 
false;
 
  246     dcbSerialParams.fOutxCtsFlow = 
false;
 
  247     dcbSerialParams.fRtsControl = 0x00;
 
  248     dcbSerialParams.fOutX = 
true;
 
  249     dcbSerialParams.fInX = 
true;
 
  252     dcbSerialParams.fOutxCtsFlow = 
true;
 
  253     dcbSerialParams.fRtsControl = 0x03;
 
  254     dcbSerialParams.fOutX = 
false;
 
  255     dcbSerialParams.fInX = 
false;
 
  259   if (!SetCommState(fd_, &dcbSerialParams)){
 
  261     THROW (IOException, 
"Error setting serial port settings.");
 
  265   COMMTIMEOUTS timeouts = {0};
 
  266   timeouts.ReadIntervalTimeout = timeout_.inter_byte_timeout;
 
  267   timeouts.ReadTotalTimeoutConstant = timeout_.read_timeout_constant;
 
  268   timeouts.ReadTotalTimeoutMultiplier = timeout_.read_timeout_multiplier;
 
  269   timeouts.WriteTotalTimeoutConstant = timeout_.write_timeout_constant;
 
  270   timeouts.WriteTotalTimeoutMultiplier = timeout_.write_timeout_multiplier;
 
  271   if (!SetCommTimeouts(fd_, &timeouts)) {
 
  272     THROW (IOException, 
"Error setting timeouts.");
 
  277 Serial::SerialImpl::close ()
 
  279   if (is_open_ == 
true) {
 
  280     if (fd_ != INVALID_HANDLE_VALUE) {
 
  282       ret = CloseHandle(fd_);
 
  285         ss << 
"Error while closing serial port: " << GetLastError();
 
  286         THROW (IOException, ss.str().c_str());
 
  288         fd_ = INVALID_HANDLE_VALUE;
 
  296 Serial::SerialImpl::isOpen ()
 const 
  302 Serial::SerialImpl::available ()
 
  308   if (!ClearCommError(fd_, NULL, &cs)) {
 
  310     ss << 
"Error while checking status of the serial port: " << GetLastError();
 
  311     THROW (IOException, ss.str().c_str());
 
  313   return static_cast<size_t>(cs.cbInQue);
 
  317 Serial::SerialImpl::waitReadable (uint32_t 
timeout)
 
  319   THROW (IOException, 
"waitReadable is not implemented on Windows.");
 
  324 Serial::SerialImpl::waitByteTimes (
size_t count)
 
  326   THROW (IOException, 
"waitByteTimes is not implemented on Windows.");
 
  330 Serial::SerialImpl::read (uint8_t *buf, 
size_t size)
 
  333     throw PortNotOpenedException (
"Serial::read");
 
  336   if (!ReadFile(fd_, buf, 
static_cast<DWORD
>(size), &bytes_read, NULL)) {
 
  338     ss << 
"Error while reading from the serial port: " << GetLastError();
 
  339     THROW (IOException, ss.str().c_str());
 
  341   return (
size_t) (bytes_read);
 
  345 Serial::SerialImpl::write (
const uint8_t *data, 
size_t length)
 
  347   if (is_open_ == 
false) {
 
  348     throw PortNotOpenedException (
"Serial::write");
 
  351   if (!WriteFile(fd_, data, 
static_cast<DWORD
>(length), &bytes_written, NULL)) {
 
  353     ss << 
"Error while writing to the serial port: " << GetLastError();
 
  354     THROW (IOException, ss.str().c_str());
 
  356   return (
size_t) (bytes_written);
 
  360 Serial::SerialImpl::setPort (
const string &port)
 
  362   port_ = wstring(port.begin(), port.end());
 
  366 Serial::SerialImpl::getPort ()
 const 
  368   return string(port_.begin(), port_.end());
 
  381 Serial::SerialImpl::getTimeout ()
 const 
  387 Serial::SerialImpl::setBaudrate (
unsigned long baudrate)
 
  389   baudrate_ = baudrate;
 
  396 Serial::SerialImpl::getBaudrate ()
 const 
  404   bytesize_ = bytesize;
 
  411 Serial::SerialImpl::getBytesize ()
 const 
  426 Serial::SerialImpl::getParity ()
 const 
  434   stopbits_ = stopbits;
 
  441 Serial::SerialImpl::getStopbits ()
 const 
  449   flowcontrol_ = flowcontrol;
 
  456 Serial::SerialImpl::getFlowcontrol ()
 const 
  462 Serial::SerialImpl::flush ()
 
  464   if (is_open_ == 
false) {
 
  465     throw PortNotOpenedException (
"Serial::flush");
 
  467   FlushFileBuffers (fd_);
 
  471 Serial::SerialImpl::flushInput ()
 
  473   THROW (IOException, 
"flushInput is not supported on Windows.");
 
  477 Serial::SerialImpl::flushOutput ()
 
  479   THROW (IOException, 
"flushOutput is not supported on Windows.");
 
  483 Serial::SerialImpl::sendBreak (
int duration)
 
  485   THROW (IOException, 
"sendBreak is not supported on Windows.");
 
  489 Serial::SerialImpl::setBreak (
bool level)
 
  491   if (is_open_ == 
false) {
 
  492     throw PortNotOpenedException (
"Serial::setBreak");
 
  495     EscapeCommFunction (fd_, SETBREAK);
 
  497     EscapeCommFunction (fd_, CLRBREAK);
 
  502 Serial::SerialImpl::setRTS (
bool level)
 
  504   if (is_open_ == 
false) {
 
  505     throw PortNotOpenedException (
"Serial::setRTS");
 
  508     EscapeCommFunction (fd_, SETRTS);
 
  510     EscapeCommFunction (fd_, CLRRTS);
 
  515 Serial::SerialImpl::setDTR (
bool level)
 
  517   if (is_open_ == 
false) {
 
  518     throw PortNotOpenedException (
"Serial::setDTR");
 
  521     EscapeCommFunction (fd_, SETDTR);
 
  523     EscapeCommFunction (fd_, CLRDTR);
 
  528 Serial::SerialImpl::waitForChange ()
 
  530   if (is_open_ == 
false) {
 
  531     throw PortNotOpenedException (
"Serial::waitForChange");
 
  535   if (!SetCommMask(fd_, EV_CTS | EV_DSR | EV_RING | EV_RLSD)) {
 
  540   if (!WaitCommEvent(fd_, &dwCommEvent, NULL)) {
 
  550 Serial::SerialImpl::getCTS ()
 
  552   if (is_open_ == 
false) {
 
  553     throw PortNotOpenedException (
"Serial::getCTS");
 
  556   if (!GetCommModemStatus(fd_, &dwModemStatus)) {
 
  557     THROW (IOException, 
"Error getting the status of the CTS line.");
 
  560   return (MS_CTS_ON & dwModemStatus) != 0;
 
  564 Serial::SerialImpl::getDSR ()
 
  566   if (is_open_ == 
false) {
 
  567     throw PortNotOpenedException (
"Serial::getDSR");
 
  570   if (!GetCommModemStatus(fd_, &dwModemStatus)) {
 
  571     THROW (IOException, 
"Error getting the status of the DSR line.");
 
  574   return (MS_DSR_ON & dwModemStatus) != 0;
 
  578 Serial::SerialImpl::getRI()
 
  580   if (is_open_ == 
false) {
 
  581     throw PortNotOpenedException (
"Serial::getRI");
 
  584   if (!GetCommModemStatus(fd_, &dwModemStatus)) {
 
  585     THROW (IOException, 
"Error getting the status of the RI line.");
 
  588   return (MS_RING_ON & dwModemStatus) != 0;
 
  592 Serial::SerialImpl::getCD()
 
  594   if (is_open_ == 
false) {
 
  595     throw PortNotOpenedException (
"Serial::getCD");
 
  598   if (!GetCommModemStatus(fd_, &dwModemStatus)) {
 
  600     THROW (IOException, 
"Error getting the status of the CD line.");
 
  603   return (MS_RLSD_ON & dwModemStatus) != 0;
 
  607 Serial::SerialImpl::readLock()
 
  609   if (WaitForSingleObject(read_mutex, INFINITE) != WAIT_OBJECT_0) {
 
  610     THROW (IOException, 
"Error claiming read mutex.");
 
  615 Serial::SerialImpl::readUnlock()
 
  617   if (!ReleaseMutex(read_mutex)) {
 
  618     THROW (IOException, 
"Error releasing read mutex.");
 
  623 Serial::SerialImpl::writeLock()
 
  625   if (WaitForSingleObject(write_mutex, INFINITE) != WAIT_OBJECT_0) {
 
  626     THROW (IOException, 
"Error claiming write mutex.");
 
  631 Serial::SerialImpl::writeUnlock()
 
  633   if (!ReleaseMutex(write_mutex)) {
 
  634     THROW (IOException, 
"Error releasing write mutex.");
 
  638 #endif // #if defined(_WIN32)