| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/serial/serial_io_handler_win.h" | 5 #include "device/serial/serial_io_handler_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <setupapi.h> | 8 #include <setupapi.h> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 // If the bitrate doesn't match that of one of the standard | 42 // If the bitrate doesn't match that of one of the standard |
| 43 // index constants, it may be provided as-is to the DCB | 43 // index constants, it may be provided as-is to the DCB |
| 44 // structure, according to MSDN. | 44 // structure, according to MSDN. |
| 45 return bitrate; | 45 return bitrate; |
| 46 } | 46 } |
| 47 #undef BITRATE_TO_SPEED_CASE | 47 #undef BITRATE_TO_SPEED_CASE |
| 48 } | 48 } |
| 49 | 49 |
| 50 int DataBitsEnumToConstant(serial::DataBits data_bits) { | 50 int DataBitsEnumToConstant(serial::DataBits data_bits) { |
| 51 switch (data_bits) { | 51 switch (data_bits) { |
| 52 case serial::DATA_BITS_SEVEN: | 52 case serial::DataBits::SEVEN: |
| 53 return 7; | 53 return 7; |
| 54 case serial::DATA_BITS_EIGHT: | 54 case serial::DataBits::EIGHT: |
| 55 default: | 55 default: |
| 56 return 8; | 56 return 8; |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | 59 |
| 60 int ParityBitEnumToConstant(serial::ParityBit parity_bit) { | 60 int ParityBitEnumToConstant(serial::ParityBit parity_bit) { |
| 61 switch (parity_bit) { | 61 switch (parity_bit) { |
| 62 case serial::PARITY_BIT_EVEN: | 62 case serial::ParityBit::EVEN: |
| 63 return EVENPARITY; | 63 return EVENPARITY; |
| 64 case serial::PARITY_BIT_ODD: | 64 case serial::ParityBit::ODD: |
| 65 return ODDPARITY; | 65 return ODDPARITY; |
| 66 case serial::PARITY_BIT_NO: | 66 case serial::ParityBit::NO: |
| 67 default: | 67 default: |
| 68 return NOPARITY; | 68 return NOPARITY; |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 | 71 |
| 72 int StopBitsEnumToConstant(serial::StopBits stop_bits) { | 72 int StopBitsEnumToConstant(serial::StopBits stop_bits) { |
| 73 switch (stop_bits) { | 73 switch (stop_bits) { |
| 74 case serial::STOP_BITS_TWO: | 74 case serial::StopBits::TWO: |
| 75 return TWOSTOPBITS; | 75 return TWOSTOPBITS; |
| 76 case serial::STOP_BITS_ONE: | 76 case serial::StopBits::ONE: |
| 77 default: | 77 default: |
| 78 return ONESTOPBIT; | 78 return ONESTOPBIT; |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 | 81 |
| 82 int SpeedConstantToBitrate(int speed) { | 82 int SpeedConstantToBitrate(int speed) { |
| 83 #define SPEED_TO_BITRATE_CASE(x) \ | 83 #define SPEED_TO_BITRATE_CASE(x) \ |
| 84 case CBR_##x: \ | 84 case CBR_##x: \ |
| 85 return x; | 85 return x; |
| 86 switch (speed) { | 86 switch (speed) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 103 // it should be an integral baud rate, according to | 103 // it should be an integral baud rate, according to |
| 104 // MSDN. | 104 // MSDN. |
| 105 return speed; | 105 return speed; |
| 106 } | 106 } |
| 107 #undef SPEED_TO_BITRATE_CASE | 107 #undef SPEED_TO_BITRATE_CASE |
| 108 } | 108 } |
| 109 | 109 |
| 110 serial::DataBits DataBitsConstantToEnum(int data_bits) { | 110 serial::DataBits DataBitsConstantToEnum(int data_bits) { |
| 111 switch (data_bits) { | 111 switch (data_bits) { |
| 112 case 7: | 112 case 7: |
| 113 return serial::DATA_BITS_SEVEN; | 113 return serial::DataBits::SEVEN; |
| 114 case 8: | 114 case 8: |
| 115 default: | 115 default: |
| 116 return serial::DATA_BITS_EIGHT; | 116 return serial::DataBits::EIGHT; |
| 117 } | 117 } |
| 118 } | 118 } |
| 119 | 119 |
| 120 serial::ParityBit ParityBitConstantToEnum(int parity_bit) { | 120 serial::ParityBit ParityBitConstantToEnum(int parity_bit) { |
| 121 switch (parity_bit) { | 121 switch (parity_bit) { |
| 122 case EVENPARITY: | 122 case EVENPARITY: |
| 123 return serial::PARITY_BIT_EVEN; | 123 return serial::ParityBit::EVEN; |
| 124 case ODDPARITY: | 124 case ODDPARITY: |
| 125 return serial::PARITY_BIT_ODD; | 125 return serial::ParityBit::ODD; |
| 126 case NOPARITY: | 126 case NOPARITY: |
| 127 default: | 127 default: |
| 128 return serial::PARITY_BIT_NO; | 128 return serial::ParityBit::NO; |
| 129 } | 129 } |
| 130 } | 130 } |
| 131 | 131 |
| 132 serial::StopBits StopBitsConstantToEnum(int stop_bits) { | 132 serial::StopBits StopBitsConstantToEnum(int stop_bits) { |
| 133 switch (stop_bits) { | 133 switch (stop_bits) { |
| 134 case TWOSTOPBITS: | 134 case TWOSTOPBITS: |
| 135 return serial::STOP_BITS_TWO; | 135 return serial::StopBits::TWO; |
| 136 case ONESTOPBIT: | 136 case ONESTOPBIT: |
| 137 default: | 137 default: |
| 138 return serial::STOP_BITS_ONE; | 138 return serial::StopBits::ONE; |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 | 141 |
| 142 // Searches for the COM port in the device's friendly name, assigns its value to | 142 // Searches for the COM port in the device's friendly name, assigns its value to |
| 143 // com_port, and returns whether the operation was successful. | 143 // com_port, and returns whether the operation was successful. |
| 144 bool GetCOMPort(const std::string friendly_name, std::string* com_port) { | 144 bool GetCOMPort(const std::string friendly_name, std::string* com_port) { |
| 145 return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port); | 145 return RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", com_port); |
| 146 } | 146 } |
| 147 | 147 |
| 148 } // namespace | 148 } // namespace |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 return; | 220 return; |
| 221 } | 221 } |
| 222 | 222 |
| 223 std::string com_port; | 223 std::string com_port; |
| 224 if (!GetCOMPort(friendly_name, &com_port)) { | 224 if (!GetCOMPort(friendly_name, &com_port)) { |
| 225 DVPLOG(1) << "Failed to get port name from \"" << friendly_name << "\"."; | 225 DVPLOG(1) << "Failed to get port name from \"" << friendly_name << "\"."; |
| 226 return; | 226 return; |
| 227 } | 227 } |
| 228 | 228 |
| 229 if (port() == com_port) | 229 if (port() == com_port) |
| 230 CancelRead(serial::RECEIVE_ERROR_DEVICE_LOST); | 230 CancelRead(serial::ReceiveError::DEVICE_LOST); |
| 231 } | 231 } |
| 232 | 232 |
| 233 bool SerialIoHandlerWin::PostOpen() { | 233 bool SerialIoHandlerWin::PostOpen() { |
| 234 DCHECK(!comm_context_); | 234 DCHECK(!comm_context_); |
| 235 DCHECK(!read_context_); | 235 DCHECK(!read_context_); |
| 236 DCHECK(!write_context_); | 236 DCHECK(!write_context_); |
| 237 | 237 |
| 238 base::MessageLoopForIO::current()->RegisterIOHandler(file().GetPlatformFile(), | 238 base::MessageLoopForIO::current()->RegisterIOHandler(file().GetPlatformFile(), |
| 239 this); | 239 this); |
| 240 | 240 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 | 278 |
| 279 if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) { | 279 if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) { |
| 280 VPLOG(1) << "Failed to set serial event flags"; | 280 VPLOG(1) << "Failed to set serial event flags"; |
| 281 } | 281 } |
| 282 | 282 |
| 283 event_mask_ = 0; | 283 event_mask_ = 0; |
| 284 BOOL ok = ::WaitCommEvent( | 284 BOOL ok = ::WaitCommEvent( |
| 285 file().GetPlatformFile(), &event_mask_, &comm_context_->overlapped); | 285 file().GetPlatformFile(), &event_mask_, &comm_context_->overlapped); |
| 286 if (!ok && GetLastError() != ERROR_IO_PENDING) { | 286 if (!ok && GetLastError() != ERROR_IO_PENDING) { |
| 287 VPLOG(1) << "Failed to receive serial event"; | 287 VPLOG(1) << "Failed to receive serial event"; |
| 288 QueueReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); | 288 QueueReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); |
| 289 } | 289 } |
| 290 is_comm_pending_ = true; | 290 is_comm_pending_ = true; |
| 291 } | 291 } |
| 292 | 292 |
| 293 void SerialIoHandlerWin::WriteImpl() { | 293 void SerialIoHandlerWin::WriteImpl() { |
| 294 DCHECK(CalledOnValidThread()); | 294 DCHECK(CalledOnValidThread()); |
| 295 DCHECK(pending_write_buffer()); | 295 DCHECK(pending_write_buffer()); |
| 296 DCHECK(file().IsValid()); | 296 DCHECK(file().IsValid()); |
| 297 | 297 |
| 298 BOOL ok = ::WriteFile(file().GetPlatformFile(), | 298 BOOL ok = ::WriteFile(file().GetPlatformFile(), |
| 299 pending_write_buffer(), | 299 pending_write_buffer(), |
| 300 pending_write_buffer_len(), | 300 pending_write_buffer_len(), |
| 301 NULL, | 301 NULL, |
| 302 &write_context_->overlapped); | 302 &write_context_->overlapped); |
| 303 if (!ok && GetLastError() != ERROR_IO_PENDING) { | 303 if (!ok && GetLastError() != ERROR_IO_PENDING) { |
| 304 VPLOG(1) << "Write failed"; | 304 VPLOG(1) << "Write failed"; |
| 305 QueueWriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR); | 305 QueueWriteCompleted(0, serial::SendError::SYSTEM_ERROR); |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 void SerialIoHandlerWin::CancelReadImpl() { | 309 void SerialIoHandlerWin::CancelReadImpl() { |
| 310 DCHECK(CalledOnValidThread()); | 310 DCHECK(CalledOnValidThread()); |
| 311 DCHECK(file().IsValid()); | 311 DCHECK(file().IsValid()); |
| 312 ::CancelIo(file().GetPlatformFile()); | 312 ::CancelIo(file().GetPlatformFile()); |
| 313 } | 313 } |
| 314 | 314 |
| 315 void SerialIoHandlerWin::CancelWriteImpl() { | 315 void SerialIoHandlerWin::CancelWriteImpl() { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 332 config.fAbortOnError = TRUE; | 332 config.fAbortOnError = TRUE; |
| 333 config.fOutxDsrFlow = FALSE; | 333 config.fOutxDsrFlow = FALSE; |
| 334 config.fDtrControl = DTR_CONTROL_ENABLE; | 334 config.fDtrControl = DTR_CONTROL_ENABLE; |
| 335 config.fDsrSensitivity = FALSE; | 335 config.fDsrSensitivity = FALSE; |
| 336 config.fOutX = FALSE; | 336 config.fOutX = FALSE; |
| 337 config.fInX = FALSE; | 337 config.fInX = FALSE; |
| 338 | 338 |
| 339 DCHECK(options().bitrate); | 339 DCHECK(options().bitrate); |
| 340 config.BaudRate = BitrateToSpeedConstant(options().bitrate); | 340 config.BaudRate = BitrateToSpeedConstant(options().bitrate); |
| 341 | 341 |
| 342 DCHECK(options().data_bits != serial::DATA_BITS_NONE); | 342 DCHECK(options().data_bits != serial::DataBits::NONE); |
| 343 config.ByteSize = DataBitsEnumToConstant(options().data_bits); | 343 config.ByteSize = DataBitsEnumToConstant(options().data_bits); |
| 344 | 344 |
| 345 DCHECK(options().parity_bit != serial::PARITY_BIT_NONE); | 345 DCHECK(options().parity_bit != serial::ParityBit::NONE); |
| 346 config.Parity = ParityBitEnumToConstant(options().parity_bit); | 346 config.Parity = ParityBitEnumToConstant(options().parity_bit); |
| 347 | 347 |
| 348 DCHECK(options().stop_bits != serial::STOP_BITS_NONE); | 348 DCHECK(options().stop_bits != serial::StopBits::NONE); |
| 349 config.StopBits = StopBitsEnumToConstant(options().stop_bits); | 349 config.StopBits = StopBitsEnumToConstant(options().stop_bits); |
| 350 | 350 |
| 351 DCHECK(options().has_cts_flow_control); | 351 DCHECK(options().has_cts_flow_control); |
| 352 if (options().cts_flow_control) { | 352 if (options().cts_flow_control) { |
| 353 config.fOutxCtsFlow = TRUE; | 353 config.fOutxCtsFlow = TRUE; |
| 354 config.fRtsControl = RTS_CONTROL_HANDSHAKE; | 354 config.fRtsControl = RTS_CONTROL_HANDSHAKE; |
| 355 } else { | 355 } else { |
| 356 config.fOutxCtsFlow = FALSE; | 356 config.fOutxCtsFlow = FALSE; |
| 357 config.fRtsControl = RTS_CONTROL_ENABLE; | 357 config.fRtsControl = RTS_CONTROL_ENABLE; |
| 358 } | 358 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 381 base::MessageLoopForIO::IOContext* context, | 381 base::MessageLoopForIO::IOContext* context, |
| 382 DWORD bytes_transferred, | 382 DWORD bytes_transferred, |
| 383 DWORD error) { | 383 DWORD error) { |
| 384 DCHECK(CalledOnValidThread()); | 384 DCHECK(CalledOnValidThread()); |
| 385 if (context == comm_context_.get()) { | 385 if (context == comm_context_.get()) { |
| 386 DWORD errors; | 386 DWORD errors; |
| 387 COMSTAT status; | 387 COMSTAT status; |
| 388 if (!ClearCommError(file().GetPlatformFile(), &errors, &status) || | 388 if (!ClearCommError(file().GetPlatformFile(), &errors, &status) || |
| 389 errors != 0) { | 389 errors != 0) { |
| 390 if (errors & CE_BREAK) { | 390 if (errors & CE_BREAK) { |
| 391 ReadCompleted(0, serial::RECEIVE_ERROR_BREAK); | 391 ReadCompleted(0, serial::ReceiveError::BREAK); |
| 392 } else if (errors & CE_FRAME) { | 392 } else if (errors & CE_FRAME) { |
| 393 ReadCompleted(0, serial::RECEIVE_ERROR_FRAME_ERROR); | 393 ReadCompleted(0, serial::ReceiveError::FRAME_ERROR); |
| 394 } else if (errors & CE_OVERRUN) { | 394 } else if (errors & CE_OVERRUN) { |
| 395 ReadCompleted(0, serial::RECEIVE_ERROR_OVERRUN); | 395 ReadCompleted(0, serial::ReceiveError::OVERRUN); |
| 396 } else if (errors & CE_RXOVER) { | 396 } else if (errors & CE_RXOVER) { |
| 397 ReadCompleted(0, serial::RECEIVE_ERROR_BUFFER_OVERFLOW); | 397 ReadCompleted(0, serial::ReceiveError::BUFFER_OVERFLOW); |
| 398 } else if (errors & CE_RXPARITY) { | 398 } else if (errors & CE_RXPARITY) { |
| 399 ReadCompleted(0, serial::RECEIVE_ERROR_PARITY_ERROR); | 399 ReadCompleted(0, serial::ReceiveError::PARITY_ERROR); |
| 400 } else { | 400 } else { |
| 401 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); | 401 ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); |
| 402 } | 402 } |
| 403 return; | 403 return; |
| 404 } | 404 } |
| 405 | 405 |
| 406 if (read_canceled()) { | 406 if (read_canceled()) { |
| 407 ReadCompleted(bytes_transferred, read_cancel_reason()); | 407 ReadCompleted(bytes_transferred, read_cancel_reason()); |
| 408 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { | 408 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { |
| 409 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); | 409 ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); |
| 410 } else if (pending_read_buffer()) { | 410 } else if (pending_read_buffer()) { |
| 411 BOOL ok = ::ReadFile(file().GetPlatformFile(), | 411 BOOL ok = ::ReadFile(file().GetPlatformFile(), |
| 412 pending_read_buffer(), | 412 pending_read_buffer(), |
| 413 pending_read_buffer_len(), | 413 pending_read_buffer_len(), |
| 414 NULL, | 414 NULL, |
| 415 &read_context_->overlapped); | 415 &read_context_->overlapped); |
| 416 if (!ok && GetLastError() != ERROR_IO_PENDING) { | 416 if (!ok && GetLastError() != ERROR_IO_PENDING) { |
| 417 VPLOG(1) << "Read failed"; | 417 VPLOG(1) << "Read failed"; |
| 418 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); | 418 ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); |
| 419 } | 419 } |
| 420 } | 420 } |
| 421 } else if (context == read_context_.get()) { | 421 } else if (context == read_context_.get()) { |
| 422 if (read_canceled()) { | 422 if (read_canceled()) { |
| 423 ReadCompleted(bytes_transferred, read_cancel_reason()); | 423 ReadCompleted(bytes_transferred, read_cancel_reason()); |
| 424 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { | 424 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { |
| 425 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); | 425 ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); |
| 426 } else { | 426 } else { |
| 427 ReadCompleted(bytes_transferred, | 427 ReadCompleted(bytes_transferred, |
| 428 error == ERROR_SUCCESS | 428 error == ERROR_SUCCESS |
| 429 ? serial::RECEIVE_ERROR_NONE | 429 ? serial::ReceiveError::NONE |
| 430 : serial::RECEIVE_ERROR_SYSTEM_ERROR); | 430 : serial::ReceiveError::SYSTEM_ERROR); |
| 431 } | 431 } |
| 432 } else if (context == write_context_.get()) { | 432 } else if (context == write_context_.get()) { |
| 433 DCHECK(pending_write_buffer()); | 433 DCHECK(pending_write_buffer()); |
| 434 if (write_canceled()) { | 434 if (write_canceled()) { |
| 435 WriteCompleted(0, write_cancel_reason()); | 435 WriteCompleted(0, write_cancel_reason()); |
| 436 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { | 436 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { |
| 437 WriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR); | 437 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); |
| 438 if (error == ERROR_GEN_FAILURE && IsReadPending()) { | 438 if (error == ERROR_GEN_FAILURE && IsReadPending()) { |
| 439 // For devices using drivers such as FTDI, CP2xxx, when device is | 439 // For devices using drivers such as FTDI, CP2xxx, when device is |
| 440 // disconnected, the context is comm_context_ and the error is | 440 // disconnected, the context is comm_context_ and the error is |
| 441 // ERROR_OPERATION_ABORTED. | 441 // ERROR_OPERATION_ABORTED. |
| 442 // However, for devices using CDC-ACM driver, when device is | 442 // However, for devices using CDC-ACM driver, when device is |
| 443 // disconnected, the context is write_context_ and the error is | 443 // disconnected, the context is write_context_ and the error is |
| 444 // ERROR_GEN_FAILURE. In this situation, in addition to a write error | 444 // ERROR_GEN_FAILURE. In this situation, in addition to a write error |
| 445 // signal, also need to generate a read error signal | 445 // signal, also need to generate a read error signal |
| 446 // serial::OnReceiveError which will notify the app about the | 446 // serial::OnReceiveError which will notify the app about the |
| 447 // disconnection. | 447 // disconnection. |
| 448 CancelRead(serial::RECEIVE_ERROR_SYSTEM_ERROR); | 448 CancelRead(serial::ReceiveError::SYSTEM_ERROR); |
| 449 } | 449 } |
| 450 } else { | 450 } else { |
| 451 WriteCompleted(bytes_transferred, | 451 WriteCompleted(bytes_transferred, error == ERROR_SUCCESS |
| 452 error == ERROR_SUCCESS ? serial::SEND_ERROR_NONE | 452 ? serial::SendError::NONE |
| 453 : serial::SEND_ERROR_SYSTEM_ERROR); | 453 : serial::SendError::SYSTEM_ERROR); |
| 454 } | 454 } |
| 455 } else { | 455 } else { |
| 456 NOTREACHED() << "Invalid IOContext"; | 456 NOTREACHED() << "Invalid IOContext"; |
| 457 } | 457 } |
| 458 } | 458 } |
| 459 | 459 |
| 460 bool SerialIoHandlerWin::Flush() const { | 460 bool SerialIoHandlerWin::Flush() const { |
| 461 if (!PurgeComm(file().GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR)) { | 461 if (!PurgeComm(file().GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR)) { |
| 462 VPLOG(1) << "Failed to flush serial port"; | 462 VPLOG(1) << "Failed to flush serial port"; |
| 463 return false; | 463 return false; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { | 534 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { |
| 535 // For COM numbers less than 9, CreateFile is called with a string such as | 535 // For COM numbers less than 9, CreateFile is called with a string such as |
| 536 // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added. | 536 // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added. |
| 537 if (port_name.length() > std::string("COM9").length()) | 537 if (port_name.length() > std::string("COM9").length()) |
| 538 return std::string("\\\\.\\").append(port_name); | 538 return std::string("\\\\.\\").append(port_name); |
| 539 | 539 |
| 540 return port_name; | 540 return port_name; |
| 541 } | 541 } |
| 542 | 542 |
| 543 } // namespace device | 543 } // namespace device |
| OLD | NEW |