Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / serial / serial_connection_win.cc
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.
4
5 #include "chrome/browser/extensions/api/serial/serial_connection.h"
6
7 #include <windows.h>
8
9 #include <string>
10
11 namespace extensions {
12
13 namespace {
14
15 int BitrateToSpeedConstant(int bitrate) {
16 #define BITRATE_TO_SPEED_CASE(x) case x: return CBR_ ## x;
17   switch (bitrate) {
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);
32     default:
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.
36       return bitrate;
37   }
38 #undef BITRATE_TO_SPEED_CASE
39 }
40
41 int DataBitsEnumToConstant(api::serial::DataBits data_bits) {
42   switch (data_bits) {
43     case api::serial::DATA_BITS_SEVEN:
44       return 7;
45     case api::serial::DATA_BITS_EIGHT:
46     default:
47       return 8;
48   }
49 }
50
51 int ParityBitEnumToConstant(api::serial::ParityBit parity_bit) {
52   switch (parity_bit) {
53     case api::serial::PARITY_BIT_EVEN:
54       return EVENPARITY;
55     case api::serial::PARITY_BIT_ODD:
56       return SPACEPARITY;
57     case api::serial::PARITY_BIT_NO:
58     default:
59       return NOPARITY;
60   }
61 }
62
63 int StopBitsEnumToConstant(api::serial::StopBits stop_bits) {
64   switch (stop_bits) {
65     case api::serial::STOP_BITS_TWO:
66       return TWOSTOPBITS;
67     case api::serial::STOP_BITS_ONE:
68     default:
69       return ONESTOPBIT;
70   }
71 }
72
73 int SpeedConstantToBitrate(int speed) {
74 #define SPEED_TO_BITRATE_CASE(x) case CBR_ ## x: return x;
75   switch (speed) {
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);
90     default:
91       // If it's not one of the standard index constants,
92       // it should be an integral baud rate, according to
93       // MSDN.
94       return speed;
95   }
96 #undef SPEED_TO_BITRATE_CASE
97 }
98
99 api::serial::DataBits DataBitsConstantToEnum(int data_bits) {
100   switch (data_bits) {
101     case 7:
102       return api::serial::DATA_BITS_SEVEN;
103     case 8:
104     default:
105       return api::serial::DATA_BITS_EIGHT;
106   }
107 }
108
109 api::serial::ParityBit ParityBitConstantToEnum(int parity_bit) {
110   switch (parity_bit) {
111     case EVENPARITY:
112       return api::serial::PARITY_BIT_EVEN;
113     case ODDPARITY:
114       return api::serial::PARITY_BIT_ODD;
115     case NOPARITY:
116     default:
117       return api::serial::PARITY_BIT_NO;
118   }
119 }
120
121 api::serial::StopBits StopBitsConstantToEnum(int stop_bits) {
122   switch (stop_bits) {
123     case TWOSTOPBITS:
124       return api::serial::STOP_BITS_TWO;
125     case ONESTOPBIT:
126     default:
127       return api::serial::STOP_BITS_ONE;
128   }
129 }
130
131 }  // namespace
132
133 bool SerialConnection::ConfigurePort(
134     const api::serial::ConnectionOptions& options) {
135   DCB config = { 0 };
136   config.DCBlength = sizeof(config);
137   if (!GetCommState(file_.GetPlatformFile(), &config)) {
138     return false;
139   }
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;
152     } else {
153       config.fOutxCtsFlow = FALSE;
154       config.fRtsControl = RTS_CONTROL_ENABLE;
155     }
156   }
157   return SetCommState(file_.GetPlatformFile(), &config) != 0;
158 }
159
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_.GetPlatformFile(), &timeouts)) {
168     return false;
169   }
170
171   DCB config = { 0 };
172   config.DCBlength = sizeof(config);
173   if (!GetCommState(file_.GetPlatformFile(), &config)) {
174     return false;
175   }
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;
186   config.fInX = FALSE;
187   return SetCommState(file_.GetPlatformFile(), &config) != 0;
188 }
189
190 bool SerialConnection::Flush() const {
191   return PurgeComm(file_.GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR) != 0;
192 }
193
194 bool SerialConnection::GetControlSignals(
195     api::serial::DeviceControlSignals* signals) const {
196   DWORD status;
197   if (!GetCommModemStatus(file_.GetPlatformFile(), &status)) {
198     return false;
199   }
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;
204   return true;
205 }
206
207 bool SerialConnection::SetControlSignals(
208     const api::serial::HostControlSignals& signals) {
209   if (signals.dtr.get()) {
210     if (!EscapeCommFunction(file_.GetPlatformFile(),
211                             *signals.dtr ? SETDTR : CLRDTR)) {
212       return false;
213     }
214   }
215   if (signals.rts.get()) {
216     if (!EscapeCommFunction(file_.GetPlatformFile(),
217                             *signals.rts ? SETRTS : CLRRTS)) {
218       return false;
219     }
220   }
221   return true;
222 }
223
224 bool SerialConnection::GetPortInfo(api::serial::ConnectionInfo* info) const {
225   DCB config = { 0 };
226   config.DCBlength = sizeof(config);
227   if (!GetCommState(file_.GetPlatformFile(), &config)) {
228     return false;
229   }
230   info->bitrate.reset(new int(SpeedConstantToBitrate(config.BaudRate)));
231   info->data_bits = DataBitsConstantToEnum(config.ByteSize);
232   info->parity_bit = ParityBitConstantToEnum(config.Parity);
233   info->stop_bits = StopBitsConstantToEnum(config.StopBits);
234   info->cts_flow_control.reset(new bool(config.fOutxCtsFlow != 0));
235   return true;
236 }
237
238 std::string SerialConnection::MaybeFixUpPortName(
239     const std::string &port_name) {
240   // For COM numbers less than 9, CreateFile is called with a string such as
241   // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added.
242   if (port_name.length() > std::string("COM9").length())
243     return std::string("\\\\.\\").append(port_name);
244
245   return port_name;
246 }
247
248 }  // namespace extensions