1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <windows.h> 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "device/serial/serial_io_handler_win.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace device { 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint BitrateToSpeedConstant(int bitrate) { 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define BITRATE_TO_SPEED_CASE(x) \ 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case x: \ 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return CBR_##x; 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (bitrate) { 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(110); 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(300); 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(600); 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(1200); 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(2400); 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(4800); 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(9600); 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(14400); 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(19200); 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(38400); 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(57600); 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(115200); 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(128000); 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BITRATE_TO_SPEED_CASE(256000); 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If the bitrate doesn't match that of one of the standard 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // index constants, it may be provided as-is to the DCB 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // structure, according to MSDN. 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return bitrate; 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#undef BITRATE_TO_SPEED_CASE 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint DataBitsEnumToConstant(serial::DataBits data_bits) { 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (data_bits) { 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::DATA_BITS_SEVEN: 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 7; 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::DATA_BITS_EIGHT: 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 8; 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint ParityBitEnumToConstant(serial::ParityBit parity_bit) { 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (parity_bit) { 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::PARITY_BIT_EVEN: 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return EVENPARITY; 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::PARITY_BIT_ODD: 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ODDPARITY; 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::PARITY_BIT_NO: 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return NOPARITY; 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint StopBitsEnumToConstant(serial::StopBits stop_bits) { 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (stop_bits) { 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::STOP_BITS_TWO: 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return TWOSTOPBITS; 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case serial::STOP_BITS_ONE: 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ONESTOPBIT; 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdochint SpeedConstantToBitrate(int speed) { 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define SPEED_TO_BITRATE_CASE(x) \ 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case CBR_##x: \ 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return x; 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (speed) { 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(110); 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(300); 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(600); 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(1200); 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(2400); 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(4800); 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(9600); 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(14400); 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(19200); 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(38400); 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(57600); 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(115200); 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(128000); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SPEED_TO_BITRATE_CASE(256000); 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If it's not one of the standard index constants, 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // it should be an integral baud rate, according to 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // MSDN. 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return speed; 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#undef SPEED_TO_BITRATE_CASE 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdochserial::DataBits DataBitsConstantToEnum(int data_bits) { 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (data_bits) { 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case 7: 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::DATA_BITS_SEVEN; 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case 8: 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::DATA_BITS_EIGHT; 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdochserial::ParityBit ParityBitConstantToEnum(int parity_bit) { 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (parity_bit) { 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case EVENPARITY: 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::PARITY_BIT_EVEN; 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case ODDPARITY: 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::PARITY_BIT_ODD; 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case NOPARITY: 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::PARITY_BIT_NO; 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdochserial::StopBits StopBitsConstantToEnum(int stop_bits) { 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch switch (stop_bits) { 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case TWOSTOPBITS: 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::STOP_BITS_TWO; 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch case ONESTOPBIT: 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch default: 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::STOP_BITS_ONE; 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)scoped_refptr<SerialIoHandler> SerialIoHandler::Create( 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::MessageLoopProxy> file_thread_message_loop) { 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new SerialIoHandlerWin(file_thread_message_loop); 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandlerWin::PostOpen() { 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!comm_context_); 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!read_context_); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!write_context_); 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoopForIO::current()->RegisterIOHandler(file().GetPlatformFile(), 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this); 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch comm_context_.reset(new base::MessageLoopForIO::IOContext()); 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch comm_context_->handler = this; 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memset(&comm_context_->overlapped, 0, sizeof(comm_context_->overlapped)); 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_context_.reset(new base::MessageLoopForIO::IOContext()); 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_context_->handler = this; 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memset(&read_context_->overlapped, 0, sizeof(read_context_->overlapped)); 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_context_.reset(new base::MessageLoopForIO::IOContext()); 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_context_->handler = this; 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped)); 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // A ReadIntervalTimeout of MAXDWORD will cause async reads to complete 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // immediately with any data that's available, even if there is none. 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // This is OK because we never issue a read request until WaitCommEvent 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // signals that data is available. 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch COMMTIMEOUTS timeouts = {0}; 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch timeouts.ReadIntervalTimeout = MAXDWORD; 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!::SetCommTimeouts(file().GetPlatformFile(), &timeouts)) { 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCB config = {0}; 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.DCBlength = sizeof(config); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!GetCommState(file().GetPlatformFile(), &config)) { 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Setup some sane default state. 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fBinary = TRUE; 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fParity = FALSE; 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fAbortOnError = TRUE; 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fOutxCtsFlow = FALSE; 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fOutxDsrFlow = FALSE; 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fRtsControl = RTS_CONTROL_ENABLE; 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fDtrControl = DTR_CONTROL_ENABLE; 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fDsrSensitivity = FALSE; 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fOutX = FALSE; 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fInX = FALSE; 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SetCommState(file().GetPlatformFile(), &config) != 0; 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandlerWin::ReadImpl() { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(pending_read_buffer()); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(file().IsValid()); 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DWORD errors; 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch COMSTAT status; 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ClearCommError(file().GetPlatformFile(), &errors, &status) || 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch errors != 0) { 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueueReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SetCommMask(file().GetPlatformFile(), EV_RXCHAR); 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch event_mask_ = 0; 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BOOL ok = ::WaitCommEvent( 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file().GetPlatformFile(), &event_mask_, &comm_context_->overlapped); 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ok && GetLastError() != ERROR_IO_PENDING) { 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueueReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch is_comm_pending_ = true; 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandlerWin::WriteImpl() { 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(pending_write_buffer()); 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(file().IsValid()); 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BOOL ok = ::WriteFile(file().GetPlatformFile(), 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_write_buffer(), 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_write_buffer_len(), 222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, 223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &write_context_->overlapped); 224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ok && GetLastError() != ERROR_IO_PENDING) { 225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QueueWriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR); 226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 229116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandlerWin::CancelReadImpl() { 230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(file().IsValid()); 232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ::CancelIo(file().GetPlatformFile()); 233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 235116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandlerWin::CancelWriteImpl() { 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(file().IsValid()); 238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ::CancelIo(file().GetPlatformFile()); 239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialIoHandlerWin::SerialIoHandlerWin( 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::MessageLoopProxy> file_thread_message_loop) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : SerialIoHandler(file_thread_message_loop), 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) event_mask_(0), 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_comm_pending_(false) { 246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 248116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSerialIoHandlerWin::~SerialIoHandlerWin() { 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandlerWin::OnIOCompleted( 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoopForIO::IOContext* context, 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DWORD bytes_transferred, 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DWORD error) { 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (context == comm_context_) { 257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (read_canceled()) { 258116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(bytes_transferred, read_cancel_reason()); 259116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (pending_read_buffer()) { 262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BOOL ok = ::ReadFile(file().GetPlatformFile(), 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_read_buffer(), 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch pending_read_buffer_len(), 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &read_context_->overlapped); 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!ok && GetLastError() != ERROR_IO_PENDING) { 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (context == read_context_) { 272116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (read_canceled()) { 273116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(bytes_transferred, read_cancel_reason()); 274116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { 275116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR); 276116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 277116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadCompleted(bytes_transferred, 278116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error == ERROR_SUCCESS 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ? serial::RECEIVE_ERROR_NONE 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : serial::RECEIVE_ERROR_SYSTEM_ERROR); 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (context == write_context_) { 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(pending_write_buffer()); 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (write_canceled()) { 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteCompleted(0, write_cancel_reason()); 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) { 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR); 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteCompleted(bytes_transferred, 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error == ERROR_SUCCESS ? serial::SEND_ERROR_NONE 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : serial::SEND_ERROR_SYSTEM_ERROR); 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 294116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NOTREACHED() << "Invalid IOContext"; 295116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 296116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 298116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandlerWin::ConfigurePort( 299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const serial::ConnectionOptions& options) { 300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCB config = {0}; 301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.DCBlength = sizeof(config); 302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!GetCommState(file().GetPlatformFile(), &config)) { 303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 305116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.bitrate) 306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.BaudRate = BitrateToSpeedConstant(options.bitrate); 307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.data_bits != serial::DATA_BITS_NONE) 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.ByteSize = DataBitsEnumToConstant(options.data_bits); 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.parity_bit != serial::PARITY_BIT_NONE) 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.Parity = ParityBitEnumToConstant(options.parity_bit); 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.stop_bits != serial::STOP_BITS_NONE) 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.StopBits = StopBitsEnumToConstant(options.stop_bits); 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.has_cts_flow_control) { 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (options.cts_flow_control) { 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fOutxCtsFlow = TRUE; 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fRtsControl = RTS_CONTROL_HANDSHAKE; 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fOutxCtsFlow = FALSE; 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.fRtsControl = RTS_CONTROL_ENABLE; 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SetCommState(file().GetPlatformFile(), &config) != 0; 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandlerWin::Flush() const { 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return PurgeComm(file().GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR) != 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 0; 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdochserial::DeviceControlSignalsPtr SerialIoHandlerWin::GetControlSignals() const { 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DWORD status; 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!GetCommModemStatus(file().GetPlatformFile(), &status)) { 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::DeviceControlSignalsPtr(); 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New()); 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals->dcd = (status & MS_RLSD_ON) != 0; 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals->cts = (status & MS_CTS_ON) != 0; 339116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals->dsr = (status & MS_DSR_ON) != 0; 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals->ri = (status & MS_RING_ON) != 0; 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return signals.Pass(); 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandlerWin::SetControlSignals( 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const serial::HostControlSignals& signals) { 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (signals.has_dtr) { 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!EscapeCommFunction(file().GetPlatformFile(), 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals.dtr ? SETDTR : CLRDTR)) { 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (signals.has_rts) { 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!EscapeCommFunction(file().GetPlatformFile(), 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch signals.rts ? SETRTS : CLRRTS)) { 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 358116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdochserial::ConnectionInfoPtr SerialIoHandlerWin::GetPortInfo() const { 362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCB config = {0}; 363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch config.DCBlength = sizeof(config); 364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!GetCommState(file().GetPlatformFile(), &config)) { 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return serial::ConnectionInfoPtr(); 366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 367116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::ConnectionInfoPtr info(serial::ConnectionInfo::New()); 368116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch info->bitrate = SpeedConstantToBitrate(config.BaudRate); 369116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch info->data_bits = DataBitsConstantToEnum(config.ByteSize); 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch info->parity_bit = ParityBitConstantToEnum(config.Parity); 371116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch info->stop_bits = StopBitsConstantToEnum(config.StopBits); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch info->cts_flow_control = config.fOutxCtsFlow != 0; 373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return info.Pass(); 374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstd::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { 377116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // For COM numbers less than 9, CreateFile is called with a string such as 378116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added. 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (port_name.length() > std::string("COM9").length()) 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return std::string("\\\\.\\").append(port_name); 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return port_name; 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace device 386