1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/serial/serial_connection.h"
11 namespace extensions {
15 int BitrateToSpeedConstant(int bitrate) {
16 #define BITRATE_TO_SPEED_CASE(x) case x: return CBR_ ## x;
18 BITRATE_TO_SPEED_CASE(110);
19 BITRATE_TO_SPEED_CASE(300);
20 BITRATE_TO_SPEED_CASE(600);
21 BITRATE_TO_SPEED_CASE(1200);
22 BITRATE_TO_SPEED_CASE(2400);
23 BITRATE_TO_SPEED_CASE(4800);
24 BITRATE_TO_SPEED_CASE(9600);
25 BITRATE_TO_SPEED_CASE(14400);
26 BITRATE_TO_SPEED_CASE(19200);
27 BITRATE_TO_SPEED_CASE(38400);
28 BITRATE_TO_SPEED_CASE(57600);
29 BITRATE_TO_SPEED_CASE(115200);
30 BITRATE_TO_SPEED_CASE(128000);
31 BITRATE_TO_SPEED_CASE(256000);
33 // If the bitrate doesn't match that of one of the standard
34 // index constants, it may be provided as-is to the DCB
35 // structure, according to MSDN.
38 #undef BITRATE_TO_SPEED_CASE
41 int DataBitsEnumToConstant(api::serial::DataBits data_bits) {
43 case api::serial::DATA_BITS_SEVEN:
45 case api::serial::DATA_BITS_EIGHT:
51 int ParityBitEnumToConstant(api::serial::ParityBit parity_bit) {
53 case api::serial::PARITY_BIT_EVEN:
55 case api::serial::PARITY_BIT_ODD:
57 case api::serial::PARITY_BIT_NO:
63 int StopBitsEnumToConstant(api::serial::StopBits stop_bits) {
65 case api::serial::STOP_BITS_TWO:
67 case api::serial::STOP_BITS_ONE:
73 int SpeedConstantToBitrate(int speed) {
74 #define SPEED_TO_BITRATE_CASE(x) case CBR_ ## x: return x;
76 SPEED_TO_BITRATE_CASE(110);
77 SPEED_TO_BITRATE_CASE(300);
78 SPEED_TO_BITRATE_CASE(600);
79 SPEED_TO_BITRATE_CASE(1200);
80 SPEED_TO_BITRATE_CASE(2400);
81 SPEED_TO_BITRATE_CASE(4800);
82 SPEED_TO_BITRATE_CASE(9600);
83 SPEED_TO_BITRATE_CASE(14400);
84 SPEED_TO_BITRATE_CASE(19200);
85 SPEED_TO_BITRATE_CASE(38400);
86 SPEED_TO_BITRATE_CASE(57600);
87 SPEED_TO_BITRATE_CASE(115200);
88 SPEED_TO_BITRATE_CASE(128000);
89 SPEED_TO_BITRATE_CASE(256000);
91 // If it's not one of the standard index constants,
92 // it should be an integral baud rate, according to
96 #undef SPEED_TO_BITRATE_CASE
99 api::serial::DataBits DataBitsConstantToEnum(int data_bits) {
102 return api::serial::DATA_BITS_SEVEN;
105 return api::serial::DATA_BITS_EIGHT;
109 api::serial::ParityBit ParityBitConstantToEnum(int parity_bit) {
110 switch (parity_bit) {
112 return api::serial::PARITY_BIT_EVEN;
114 return api::serial::PARITY_BIT_ODD;
117 return api::serial::PARITY_BIT_NO;
121 api::serial::StopBits StopBitsConstantToEnum(int stop_bits) {
124 return api::serial::STOP_BITS_TWO;
127 return api::serial::STOP_BITS_ONE;
133 bool SerialConnection::ConfigurePort(
134 const api::serial::ConnectionOptions& options) {
136 config.DCBlength = sizeof(config);
137 if (!GetCommState(file_, &config)) {
140 if (options.bitrate.get())
141 config.BaudRate = BitrateToSpeedConstant(*options.bitrate);
142 if (options.data_bits != api::serial::DATA_BITS_NONE)
143 config.ByteSize = DataBitsEnumToConstant(options.data_bits);
144 if (options.parity_bit != api::serial::PARITY_BIT_NONE)
145 config.Parity = ParityBitEnumToConstant(options.parity_bit);
146 if (options.stop_bits != api::serial::STOP_BITS_NONE)
147 config.StopBits = StopBitsEnumToConstant(options.stop_bits);
148 if (options.cts_flow_control.get()) {
149 if (*options.cts_flow_control) {
150 config.fOutxCtsFlow = TRUE;
151 config.fRtsControl = RTS_CONTROL_HANDSHAKE;
153 config.fOutxCtsFlow = FALSE;
154 config.fRtsControl = RTS_CONTROL_ENABLE;
157 return SetCommState(file_, &config) != 0;
160 bool SerialConnection::PostOpen() {
161 // A ReadIntervalTimeout of MAXDWORD will cause async reads to complete
162 // immediately with any data that's available, even if there is none.
163 // This is OK because we never issue a read request until WaitCommEvent
164 // signals that data is available.
165 COMMTIMEOUTS timeouts = { 0 };
166 timeouts.ReadIntervalTimeout = MAXDWORD;
167 if (!::SetCommTimeouts(file_, &timeouts)) {
172 config.DCBlength = sizeof(config);
173 if (!GetCommState(file_, &config)) {
176 // Setup some sane default state.
177 config.fBinary = TRUE;
178 config.fParity = FALSE;
179 config.fAbortOnError = TRUE;
180 config.fOutxCtsFlow = FALSE;
181 config.fOutxDsrFlow = FALSE;
182 config.fRtsControl = RTS_CONTROL_ENABLE;
183 config.fDtrControl = DTR_CONTROL_ENABLE;
184 config.fDsrSensitivity = FALSE;
185 config.fOutX = FALSE;
187 return SetCommState(file_, &config) != 0;
190 bool SerialConnection::Flush() const {
191 return PurgeComm(file_, PURGE_RXCLEAR | PURGE_TXCLEAR) != 0;
194 bool SerialConnection::GetControlSignals(
195 api::serial::DeviceControlSignals* signals) const {
197 if (!GetCommModemStatus(file_, &status)) {
200 signals->dcd = (status & MS_RLSD_ON) != 0;
201 signals->cts = (status & MS_CTS_ON) != 0;
202 signals->dsr = (status & MS_DSR_ON) != 0;
203 signals->ri = (status & MS_RING_ON) != 0;
207 bool SerialConnection::SetControlSignals(
208 const api::serial::HostControlSignals& signals) {
209 if (signals.dtr.get()) {
210 if (!EscapeCommFunction(file_, *signals.dtr ? SETDTR : CLRDTR)) {
214 if (signals.rts.get()) {
215 if (!EscapeCommFunction(file_, *signals.rts ? SETRTS : CLRRTS)) {
222 bool SerialConnection::GetPortInfo(api::serial::ConnectionInfo* info) const {
224 config.DCBlength = sizeof(config);
225 if (!GetCommState(file_, &config)) {
228 info->bitrate.reset(new int(SpeedConstantToBitrate(config.BaudRate)));
229 info->data_bits = DataBitsConstantToEnum(config.ByteSize);
230 info->parity_bit = ParityBitConstantToEnum(config.Parity);
231 info->stop_bits = StopBitsConstantToEnum(config.StopBits);
232 info->cts_flow_control.reset(new bool(config.fOutxCtsFlow != 0));
236 std::string SerialConnection::MaybeFixUpPortName(
237 const std::string &port_name) {
238 // For COM numbers less than 9, CreateFile is called with a string such as
239 // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added.
240 if (port_name.length() > std::string("COM9").length())
241 return std::string("\\\\.\\").append(port_name);
246 } // namespace extensions