GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / device / serial / serial_io_handler_win.cc
blob40f50236af79ad8ca2f8d1249d5d03486b3a0882
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
3 // found in the LICENSE file.
5 #include <windows.h>
7 #include "device/serial/serial_io_handler_win.h"
9 namespace device {
11 namespace {
13 int BitrateToSpeedConstant(int bitrate) {
14 #define BITRATE_TO_SPEED_CASE(x) \
15 case x: \
16 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;
38 #undef BITRATE_TO_SPEED_CASE
41 int DataBitsEnumToConstant(serial::DataBits data_bits) {
42 switch (data_bits) {
43 case serial::DATA_BITS_SEVEN:
44 return 7;
45 case serial::DATA_BITS_EIGHT:
46 default:
47 return 8;
51 int ParityBitEnumToConstant(serial::ParityBit parity_bit) {
52 switch (parity_bit) {
53 case serial::PARITY_BIT_EVEN:
54 return EVENPARITY;
55 case serial::PARITY_BIT_ODD:
56 return ODDPARITY;
57 case serial::PARITY_BIT_NO:
58 default:
59 return NOPARITY;
63 int StopBitsEnumToConstant(serial::StopBits stop_bits) {
64 switch (stop_bits) {
65 case serial::STOP_BITS_TWO:
66 return TWOSTOPBITS;
67 case serial::STOP_BITS_ONE:
68 default:
69 return ONESTOPBIT;
73 int SpeedConstantToBitrate(int speed) {
74 #define SPEED_TO_BITRATE_CASE(x) \
75 case CBR_##x: \
76 return x;
77 switch (speed) {
78 SPEED_TO_BITRATE_CASE(110);
79 SPEED_TO_BITRATE_CASE(300);
80 SPEED_TO_BITRATE_CASE(600);
81 SPEED_TO_BITRATE_CASE(1200);
82 SPEED_TO_BITRATE_CASE(2400);
83 SPEED_TO_BITRATE_CASE(4800);
84 SPEED_TO_BITRATE_CASE(9600);
85 SPEED_TO_BITRATE_CASE(14400);
86 SPEED_TO_BITRATE_CASE(19200);
87 SPEED_TO_BITRATE_CASE(38400);
88 SPEED_TO_BITRATE_CASE(57600);
89 SPEED_TO_BITRATE_CASE(115200);
90 SPEED_TO_BITRATE_CASE(128000);
91 SPEED_TO_BITRATE_CASE(256000);
92 default:
93 // If it's not one of the standard index constants,
94 // it should be an integral baud rate, according to
95 // MSDN.
96 return speed;
98 #undef SPEED_TO_BITRATE_CASE
101 serial::DataBits DataBitsConstantToEnum(int data_bits) {
102 switch (data_bits) {
103 case 7:
104 return serial::DATA_BITS_SEVEN;
105 case 8:
106 default:
107 return serial::DATA_BITS_EIGHT;
111 serial::ParityBit ParityBitConstantToEnum(int parity_bit) {
112 switch (parity_bit) {
113 case EVENPARITY:
114 return serial::PARITY_BIT_EVEN;
115 case ODDPARITY:
116 return serial::PARITY_BIT_ODD;
117 case NOPARITY:
118 default:
119 return serial::PARITY_BIT_NO;
123 serial::StopBits StopBitsConstantToEnum(int stop_bits) {
124 switch (stop_bits) {
125 case TWOSTOPBITS:
126 return serial::STOP_BITS_TWO;
127 case ONESTOPBIT:
128 default:
129 return serial::STOP_BITS_ONE;
133 } // namespace
135 // static
136 scoped_refptr<SerialIoHandler> SerialIoHandler::Create(
137 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop,
138 scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) {
139 return new SerialIoHandlerWin(file_thread_message_loop,
140 ui_thread_message_loop);
143 bool SerialIoHandlerWin::PostOpen() {
144 DCHECK(!comm_context_);
145 DCHECK(!read_context_);
146 DCHECK(!write_context_);
148 base::MessageLoopForIO::current()->RegisterIOHandler(file().GetPlatformFile(),
149 this);
151 comm_context_.reset(new base::MessageLoopForIO::IOContext());
152 comm_context_->handler = this;
153 memset(&comm_context_->overlapped, 0, sizeof(comm_context_->overlapped));
155 read_context_.reset(new base::MessageLoopForIO::IOContext());
156 read_context_->handler = this;
157 memset(&read_context_->overlapped, 0, sizeof(read_context_->overlapped));
159 write_context_.reset(new base::MessageLoopForIO::IOContext());
160 write_context_->handler = this;
161 memset(&write_context_->overlapped, 0, sizeof(write_context_->overlapped));
163 // A ReadIntervalTimeout of MAXDWORD will cause async reads to complete
164 // immediately with any data that's available, even if there is none.
165 // This is OK because we never issue a read request until WaitCommEvent
166 // signals that data is available.
167 COMMTIMEOUTS timeouts = {0};
168 timeouts.ReadIntervalTimeout = MAXDWORD;
169 if (!::SetCommTimeouts(file().GetPlatformFile(), &timeouts)) {
170 VPLOG(1) << "Failed to set serial timeouts";
171 return false;
174 return true;
177 void SerialIoHandlerWin::ReadImpl() {
178 DCHECK(CalledOnValidThread());
179 DCHECK(pending_read_buffer());
180 DCHECK(file().IsValid());
182 DWORD errors;
183 COMSTAT status;
184 if (!ClearCommError(file().GetPlatformFile(), &errors, &status) ||
185 errors != 0) {
186 QueueReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR);
187 return;
190 if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) {
191 VPLOG(1) << "Failed to set serial event flags";
194 event_mask_ = 0;
195 BOOL ok = ::WaitCommEvent(
196 file().GetPlatformFile(), &event_mask_, &comm_context_->overlapped);
197 if (!ok && GetLastError() != ERROR_IO_PENDING) {
198 VPLOG(1) << "Failed to receive serial event";
199 QueueReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR);
201 is_comm_pending_ = true;
204 void SerialIoHandlerWin::WriteImpl() {
205 DCHECK(CalledOnValidThread());
206 DCHECK(pending_write_buffer());
207 DCHECK(file().IsValid());
209 BOOL ok = ::WriteFile(file().GetPlatformFile(),
210 pending_write_buffer(),
211 pending_write_buffer_len(),
212 NULL,
213 &write_context_->overlapped);
214 if (!ok && GetLastError() != ERROR_IO_PENDING) {
215 QueueWriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR);
219 void SerialIoHandlerWin::CancelReadImpl() {
220 DCHECK(CalledOnValidThread());
221 DCHECK(file().IsValid());
222 ::CancelIo(file().GetPlatformFile());
225 void SerialIoHandlerWin::CancelWriteImpl() {
226 DCHECK(CalledOnValidThread());
227 DCHECK(file().IsValid());
228 ::CancelIo(file().GetPlatformFile());
231 bool SerialIoHandlerWin::ConfigurePortImpl() {
232 DCB config = {0};
233 config.DCBlength = sizeof(config);
234 if (!GetCommState(file().GetPlatformFile(), &config)) {
235 VPLOG(1) << "Failed to get serial port info";
236 return false;
239 // Set up some sane default options that are not configurable.
240 config.fBinary = TRUE;
241 config.fParity = FALSE;
242 config.fAbortOnError = TRUE;
243 config.fOutxDsrFlow = FALSE;
244 config.fDtrControl = DTR_CONTROL_ENABLE;
245 config.fDsrSensitivity = FALSE;
246 config.fOutX = FALSE;
247 config.fInX = FALSE;
249 DCHECK(options().bitrate);
250 config.BaudRate = BitrateToSpeedConstant(options().bitrate);
252 DCHECK(options().data_bits != serial::DATA_BITS_NONE);
253 config.ByteSize = DataBitsEnumToConstant(options().data_bits);
255 DCHECK(options().parity_bit != serial::PARITY_BIT_NONE);
256 config.Parity = ParityBitEnumToConstant(options().parity_bit);
258 DCHECK(options().stop_bits != serial::STOP_BITS_NONE);
259 config.StopBits = StopBitsEnumToConstant(options().stop_bits);
261 DCHECK(options().has_cts_flow_control);
262 if (options().cts_flow_control) {
263 config.fOutxCtsFlow = TRUE;
264 config.fRtsControl = RTS_CONTROL_HANDSHAKE;
265 } else {
266 config.fOutxCtsFlow = FALSE;
267 config.fRtsControl = RTS_CONTROL_ENABLE;
270 if (!SetCommState(file().GetPlatformFile(), &config)) {
271 VPLOG(1) << "Failed to set serial port info";
272 return false;
274 return true;
277 SerialIoHandlerWin::SerialIoHandlerWin(
278 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop,
279 scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop)
280 : SerialIoHandler(file_thread_message_loop, ui_thread_message_loop),
281 event_mask_(0),
282 is_comm_pending_(false) {
285 SerialIoHandlerWin::~SerialIoHandlerWin() {
288 void SerialIoHandlerWin::OnIOCompleted(
289 base::MessageLoopForIO::IOContext* context,
290 DWORD bytes_transferred,
291 DWORD error) {
292 DCHECK(CalledOnValidThread());
293 if (context == comm_context_) {
294 if (read_canceled()) {
295 ReadCompleted(bytes_transferred, read_cancel_reason());
296 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
297 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR);
298 } else if (pending_read_buffer()) {
299 BOOL ok = ::ReadFile(file().GetPlatformFile(),
300 pending_read_buffer(),
301 pending_read_buffer_len(),
302 NULL,
303 &read_context_->overlapped);
304 if (!ok && GetLastError() != ERROR_IO_PENDING) {
305 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR);
308 } else if (context == read_context_) {
309 if (read_canceled()) {
310 ReadCompleted(bytes_transferred, read_cancel_reason());
311 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
312 ReadCompleted(0, serial::RECEIVE_ERROR_SYSTEM_ERROR);
313 } else {
314 ReadCompleted(bytes_transferred,
315 error == ERROR_SUCCESS
316 ? serial::RECEIVE_ERROR_NONE
317 : serial::RECEIVE_ERROR_SYSTEM_ERROR);
319 } else if (context == write_context_) {
320 DCHECK(pending_write_buffer());
321 if (write_canceled()) {
322 WriteCompleted(0, write_cancel_reason());
323 } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
324 WriteCompleted(0, serial::SEND_ERROR_SYSTEM_ERROR);
325 } else {
326 WriteCompleted(bytes_transferred,
327 error == ERROR_SUCCESS ? serial::SEND_ERROR_NONE
328 : serial::SEND_ERROR_SYSTEM_ERROR);
330 } else {
331 NOTREACHED() << "Invalid IOContext";
335 bool SerialIoHandlerWin::Flush() const {
336 if (!PurgeComm(file().GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR)) {
337 VPLOG(1) << "Failed to flush serial port";
338 return false;
340 return true;
343 serial::DeviceControlSignalsPtr SerialIoHandlerWin::GetControlSignals() const {
344 DWORD status;
345 if (!GetCommModemStatus(file().GetPlatformFile(), &status)) {
346 VPLOG(1) << "Failed to get port control signals";
347 return serial::DeviceControlSignalsPtr();
350 serial::DeviceControlSignalsPtr signals(serial::DeviceControlSignals::New());
351 signals->dcd = (status & MS_RLSD_ON) != 0;
352 signals->cts = (status & MS_CTS_ON) != 0;
353 signals->dsr = (status & MS_DSR_ON) != 0;
354 signals->ri = (status & MS_RING_ON) != 0;
355 return signals.Pass();
358 bool SerialIoHandlerWin::SetControlSignals(
359 const serial::HostControlSignals& signals) {
360 if (signals.has_dtr) {
361 if (!EscapeCommFunction(file().GetPlatformFile(),
362 signals.dtr ? SETDTR : CLRDTR)) {
363 VPLOG(1) << "Failed to configure DTR signal";
364 return false;
367 if (signals.has_rts) {
368 if (!EscapeCommFunction(file().GetPlatformFile(),
369 signals.rts ? SETRTS : CLRRTS)) {
370 VPLOG(1) << "Failed to configure RTS signal";
371 return false;
374 return true;
377 serial::ConnectionInfoPtr SerialIoHandlerWin::GetPortInfo() const {
378 DCB config = {0};
379 config.DCBlength = sizeof(config);
380 if (!GetCommState(file().GetPlatformFile(), &config)) {
381 VPLOG(1) << "Failed to get serial port info";
382 return serial::ConnectionInfoPtr();
384 serial::ConnectionInfoPtr info(serial::ConnectionInfo::New());
385 info->bitrate = SpeedConstantToBitrate(config.BaudRate);
386 info->data_bits = DataBitsConstantToEnum(config.ByteSize);
387 info->parity_bit = ParityBitConstantToEnum(config.Parity);
388 info->stop_bits = StopBitsConstantToEnum(config.StopBits);
389 info->cts_flow_control = config.fOutxCtsFlow != 0;
390 return info.Pass();
393 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) {
394 // For COM numbers less than 9, CreateFile is called with a string such as
395 // "COM1". For numbers greater than 9, a prefix of "\\\\.\\" must be added.
396 if (port_name.length() > std::string("COM9").length())
397 return std::string("\\\\.\\").append(port_name);
399 return port_name;
402 } // namespace device