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 "extensions/browser/api/serial/serial_connection.h"
10 #include "base/files/file_path.h"
11 #include "base/lazy_instance.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "extensions/browser/api/api_resource_manager.h"
15 #include "extensions/common/api/serial.h"
17 namespace extensions
{
21 const int kDefaultBufferSize
= 4096;
23 api::serial::SendError
ConvertSendErrorFromMojo(
24 device::serial::SendError input
) {
26 case device::serial::SEND_ERROR_NONE
:
27 return api::serial::SEND_ERROR_NONE
;
28 case device::serial::SEND_ERROR_DISCONNECTED
:
29 return api::serial::SEND_ERROR_DISCONNECTED
;
30 case device::serial::SEND_ERROR_PENDING
:
31 return api::serial::SEND_ERROR_PENDING
;
32 case device::serial::SEND_ERROR_TIMEOUT
:
33 return api::serial::SEND_ERROR_TIMEOUT
;
34 case device::serial::SEND_ERROR_SYSTEM_ERROR
:
35 return api::serial::SEND_ERROR_SYSTEM_ERROR
;
37 return api::serial::SEND_ERROR_NONE
;
40 api::serial::ReceiveError
ConvertReceiveErrorFromMojo(
41 device::serial::ReceiveError input
) {
43 case device::serial::RECEIVE_ERROR_NONE
:
44 return api::serial::RECEIVE_ERROR_NONE
;
45 case device::serial::RECEIVE_ERROR_DISCONNECTED
:
46 return api::serial::RECEIVE_ERROR_DISCONNECTED
;
47 case device::serial::RECEIVE_ERROR_TIMEOUT
:
48 return api::serial::RECEIVE_ERROR_TIMEOUT
;
49 case device::serial::RECEIVE_ERROR_DEVICE_LOST
:
50 return api::serial::RECEIVE_ERROR_DEVICE_LOST
;
51 case device::serial::RECEIVE_ERROR_BREAK
:
52 return api::serial::RECEIVE_ERROR_BREAK
;
53 case device::serial::RECEIVE_ERROR_FRAME_ERROR
:
54 return api::serial::RECEIVE_ERROR_FRAME_ERROR
;
55 case device::serial::RECEIVE_ERROR_OVERRUN
:
56 return api::serial::RECEIVE_ERROR_OVERRUN
;
57 case device::serial::RECEIVE_ERROR_BUFFER_OVERFLOW
:
58 return api::serial::RECEIVE_ERROR_BUFFER_OVERFLOW
;
59 case device::serial::RECEIVE_ERROR_PARITY_ERROR
:
60 return api::serial::RECEIVE_ERROR_PARITY_ERROR
;
61 case device::serial::RECEIVE_ERROR_SYSTEM_ERROR
:
62 return api::serial::RECEIVE_ERROR_SYSTEM_ERROR
;
64 return api::serial::RECEIVE_ERROR_NONE
;
67 api::serial::DataBits
ConvertDataBitsFromMojo(device::serial::DataBits input
) {
69 case device::serial::DATA_BITS_NONE
:
70 return api::serial::DATA_BITS_NONE
;
71 case device::serial::DATA_BITS_SEVEN
:
72 return api::serial::DATA_BITS_SEVEN
;
73 case device::serial::DATA_BITS_EIGHT
:
74 return api::serial::DATA_BITS_EIGHT
;
76 return api::serial::DATA_BITS_NONE
;
79 device::serial::DataBits
ConvertDataBitsToMojo(api::serial::DataBits input
) {
81 case api::serial::DATA_BITS_NONE
:
82 return device::serial::DATA_BITS_NONE
;
83 case api::serial::DATA_BITS_SEVEN
:
84 return device::serial::DATA_BITS_SEVEN
;
85 case api::serial::DATA_BITS_EIGHT
:
86 return device::serial::DATA_BITS_EIGHT
;
88 return device::serial::DATA_BITS_NONE
;
91 api::serial::ParityBit
ConvertParityBitFromMojo(
92 device::serial::ParityBit input
) {
94 case device::serial::PARITY_BIT_NONE
:
95 return api::serial::PARITY_BIT_NONE
;
96 case device::serial::PARITY_BIT_ODD
:
97 return api::serial::PARITY_BIT_ODD
;
98 case device::serial::PARITY_BIT_NO
:
99 return api::serial::PARITY_BIT_NO
;
100 case device::serial::PARITY_BIT_EVEN
:
101 return api::serial::PARITY_BIT_EVEN
;
103 return api::serial::PARITY_BIT_NONE
;
106 device::serial::ParityBit
ConvertParityBitToMojo(api::serial::ParityBit input
) {
108 case api::serial::PARITY_BIT_NONE
:
109 return device::serial::PARITY_BIT_NONE
;
110 case api::serial::PARITY_BIT_NO
:
111 return device::serial::PARITY_BIT_NO
;
112 case api::serial::PARITY_BIT_ODD
:
113 return device::serial::PARITY_BIT_ODD
;
114 case api::serial::PARITY_BIT_EVEN
:
115 return device::serial::PARITY_BIT_EVEN
;
117 return device::serial::PARITY_BIT_NONE
;
120 api::serial::StopBits
ConvertStopBitsFromMojo(device::serial::StopBits input
) {
122 case device::serial::STOP_BITS_NONE
:
123 return api::serial::STOP_BITS_NONE
;
124 case device::serial::STOP_BITS_ONE
:
125 return api::serial::STOP_BITS_ONE
;
126 case device::serial::STOP_BITS_TWO
:
127 return api::serial::STOP_BITS_TWO
;
129 return api::serial::STOP_BITS_NONE
;
132 device::serial::StopBits
ConvertStopBitsToMojo(api::serial::StopBits input
) {
134 case api::serial::STOP_BITS_NONE
:
135 return device::serial::STOP_BITS_NONE
;
136 case api::serial::STOP_BITS_ONE
:
137 return device::serial::STOP_BITS_ONE
;
138 case api::serial::STOP_BITS_TWO
:
139 return device::serial::STOP_BITS_TWO
;
141 return device::serial::STOP_BITS_NONE
;
144 class SendBuffer
: public device::ReadOnlyBuffer
{
147 const std::vector
<char>& data
,
148 const base::Callback
<void(int, device::serial::SendError
)>& callback
)
149 : data_(data
), callback_(callback
) {}
150 ~SendBuffer() override
{}
151 const char* GetData() override
{ return vector_as_array(&data_
); }
152 uint32_t GetSize() override
{ return static_cast<uint32_t>(data_
.size()); }
153 void Done(uint32_t bytes_read
) override
{
154 callback_
.Run(bytes_read
, device::serial::SEND_ERROR_NONE
);
156 void DoneWithError(uint32_t bytes_read
, int32_t error
) override
{
157 callback_
.Run(bytes_read
, static_cast<device::serial::SendError
>(error
));
161 const std::vector
<char> data_
;
162 const base::Callback
<void(int, device::serial::SendError
)> callback_
;
165 class ReceiveBuffer
: public device::WritableBuffer
{
168 scoped_refptr
<net::IOBuffer
> buffer
,
170 const base::Callback
<void(int, device::serial::ReceiveError
)>& callback
)
171 : buffer_(buffer
), size_(size
), callback_(callback
) {}
172 ~ReceiveBuffer() override
{}
173 char* GetData() override
{ return buffer_
->data(); }
174 uint32_t GetSize() override
{ return size_
; }
175 void Done(uint32_t bytes_written
) override
{
176 callback_
.Run(bytes_written
, device::serial::RECEIVE_ERROR_NONE
);
178 void DoneWithError(uint32_t bytes_written
, int32_t error
) override
{
179 callback_
.Run(bytes_written
,
180 static_cast<device::serial::ReceiveError
>(error
));
184 scoped_refptr
<net::IOBuffer
> buffer_
;
185 const uint32_t size_
;
186 const base::Callback
<void(int, device::serial::ReceiveError
)> callback_
;
191 static base::LazyInstance
<
192 BrowserContextKeyedAPIFactory
<ApiResourceManager
<SerialConnection
> > >
193 g_factory
= LAZY_INSTANCE_INITIALIZER
;
197 BrowserContextKeyedAPIFactory
<ApiResourceManager
<SerialConnection
> >*
198 ApiResourceManager
<SerialConnection
>::GetFactoryInstance() {
199 return g_factory
.Pointer();
202 SerialConnection::SerialConnection(const std::string
& port
,
203 const std::string
& owner_extension_id
)
204 : ApiResource(owner_extension_id
),
207 buffer_size_(kDefaultBufferSize
),
211 io_handler_(device::SerialIoHandler::Create(
212 content::BrowserThread::GetMessageLoopProxyForThread(
213 content::BrowserThread::FILE),
214 content::BrowserThread::GetMessageLoopProxyForThread(
215 content::BrowserThread::UI
))) {
216 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
219 SerialConnection::~SerialConnection() {
220 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_DISCONNECTED
);
221 io_handler_
->CancelWrite(device::serial::SEND_ERROR_DISCONNECTED
);
224 bool SerialConnection::IsPersistent() const {
228 void SerialConnection::set_buffer_size(int buffer_size
) {
229 buffer_size_
= buffer_size
;
232 void SerialConnection::set_receive_timeout(int receive_timeout
) {
233 receive_timeout_
= receive_timeout
;
236 void SerialConnection::set_send_timeout(int send_timeout
) {
237 send_timeout_
= send_timeout
;
240 void SerialConnection::set_paused(bool paused
) {
243 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_NONE
);
247 void SerialConnection::Open(const api::serial::ConnectionOptions
& options
,
248 const OpenCompleteCallback
& callback
) {
249 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
250 if (options
.persistent
.get())
251 set_persistent(*options
.persistent
);
252 if (options
.name
.get())
253 set_name(*options
.name
);
254 if (options
.buffer_size
.get())
255 set_buffer_size(*options
.buffer_size
);
256 if (options
.receive_timeout
.get())
257 set_receive_timeout(*options
.receive_timeout
);
258 if (options
.send_timeout
.get())
259 set_send_timeout(*options
.send_timeout
);
260 io_handler_
->Open(port_
, *device::serial::ConnectionOptions::From(options
),
264 bool SerialConnection::Receive(const ReceiveCompleteCallback
& callback
) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
266 if (!receive_complete_
.is_null())
268 receive_complete_
= callback
;
269 receive_buffer_
= new net::IOBuffer(buffer_size_
);
270 io_handler_
->Read(scoped_ptr
<device::WritableBuffer
>(new ReceiveBuffer(
273 base::Bind(&SerialConnection::OnAsyncReadComplete
, AsWeakPtr()))));
274 receive_timeout_task_
.reset();
275 if (receive_timeout_
> 0) {
276 receive_timeout_task_
.reset(new TimeoutTask(
277 base::Bind(&SerialConnection::OnReceiveTimeout
, AsWeakPtr()),
278 base::TimeDelta::FromMilliseconds(receive_timeout_
)));
283 bool SerialConnection::Send(const std::vector
<char>& data
,
284 const SendCompleteCallback
& callback
) {
285 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
286 if (!send_complete_
.is_null())
288 send_complete_
= callback
;
289 io_handler_
->Write(scoped_ptr
<device::ReadOnlyBuffer
>(new SendBuffer(
290 data
, base::Bind(&SerialConnection::OnAsyncWriteComplete
, AsWeakPtr()))));
291 send_timeout_task_
.reset();
292 if (send_timeout_
> 0) {
293 send_timeout_task_
.reset(new TimeoutTask(
294 base::Bind(&SerialConnection::OnSendTimeout
, AsWeakPtr()),
295 base::TimeDelta::FromMilliseconds(send_timeout_
)));
300 bool SerialConnection::Configure(
301 const api::serial::ConnectionOptions
& options
) {
302 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
303 if (options
.persistent
.get())
304 set_persistent(*options
.persistent
);
305 if (options
.name
.get())
306 set_name(*options
.name
);
307 if (options
.buffer_size
.get())
308 set_buffer_size(*options
.buffer_size
);
309 if (options
.receive_timeout
.get())
310 set_receive_timeout(*options
.receive_timeout
);
311 if (options
.send_timeout
.get())
312 set_send_timeout(*options
.send_timeout
);
313 bool success
= io_handler_
->ConfigurePort(
314 *device::serial::ConnectionOptions::From(options
));
315 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_NONE
);
319 void SerialConnection::SetIoHandlerForTest(
320 scoped_refptr
<device::SerialIoHandler
> handler
) {
321 io_handler_
= handler
;
324 bool SerialConnection::GetInfo(api::serial::ConnectionInfo
* info
) const {
325 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
326 info
->paused
= paused_
;
327 info
->persistent
= persistent_
;
329 info
->buffer_size
= buffer_size_
;
330 info
->receive_timeout
= receive_timeout_
;
331 info
->send_timeout
= send_timeout_
;
332 device::serial::ConnectionInfoPtr port_info
= io_handler_
->GetPortInfo();
336 info
->bitrate
.reset(new int(port_info
->bitrate
));
337 info
->data_bits
= ConvertDataBitsFromMojo(port_info
->data_bits
);
338 info
->parity_bit
= ConvertParityBitFromMojo(port_info
->parity_bit
);
339 info
->stop_bits
= ConvertStopBitsFromMojo(port_info
->stop_bits
);
340 info
->cts_flow_control
.reset(new bool(port_info
->cts_flow_control
));
344 bool SerialConnection::Flush() const {
345 return io_handler_
->Flush();
348 bool SerialConnection::GetControlSignals(
349 api::serial::DeviceControlSignals
* control_signals
) const {
350 device::serial::DeviceControlSignalsPtr signals
=
351 io_handler_
->GetControlSignals();
355 control_signals
->dcd
= signals
->dcd
;
356 control_signals
->cts
= signals
->cts
;
357 control_signals
->ri
= signals
->ri
;
358 control_signals
->dsr
= signals
->dsr
;
362 bool SerialConnection::SetControlSignals(
363 const api::serial::HostControlSignals
& control_signals
) {
364 return io_handler_
->SetControlSignals(
365 *device::serial::HostControlSignals::From(control_signals
));
368 bool SerialConnection::SetBreak() {
369 return io_handler_
->SetBreak();
372 bool SerialConnection::ClearBreak() {
373 return io_handler_
->ClearBreak();
376 void SerialConnection::OnReceiveTimeout() {
377 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
378 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_TIMEOUT
);
381 void SerialConnection::OnSendTimeout() {
382 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
383 io_handler_
->CancelWrite(device::serial::SEND_ERROR_TIMEOUT
);
386 void SerialConnection::OnAsyncReadComplete(int bytes_read
,
387 device::serial::ReceiveError error
) {
388 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
389 DCHECK(!receive_complete_
.is_null());
390 ReceiveCompleteCallback callback
= receive_complete_
;
391 receive_complete_
.Reset();
392 receive_timeout_task_
.reset();
393 callback
.Run(std::vector
<char>(receive_buffer_
->data(),
394 receive_buffer_
->data() + bytes_read
),
395 ConvertReceiveErrorFromMojo(error
));
396 receive_buffer_
= NULL
;
399 void SerialConnection::OnAsyncWriteComplete(int bytes_sent
,
400 device::serial::SendError error
) {
401 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
402 DCHECK(!send_complete_
.is_null());
403 SendCompleteCallback callback
= send_complete_
;
404 send_complete_
.Reset();
405 send_timeout_task_
.reset();
406 callback
.Run(bytes_sent
, ConvertSendErrorFromMojo(error
));
409 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure
& closure
,
410 const base::TimeDelta
& delay
)
411 : closure_(closure
), delay_(delay
), weak_factory_(this) {
412 base::MessageLoop::current()->PostDelayedTask(
414 base::Bind(&TimeoutTask::Run
, weak_factory_
.GetWeakPtr()),
418 SerialConnection::TimeoutTask::~TimeoutTask() {
421 void SerialConnection::TimeoutTask::Run() const {
425 } // namespace extensions
430 device::serial::HostControlSignalsPtr
431 TypeConverter
<device::serial::HostControlSignalsPtr
,
432 extensions::api::serial::HostControlSignals
>::
433 Convert(const extensions::api::serial::HostControlSignals
& input
) {
434 device::serial::HostControlSignalsPtr
output(
435 device::serial::HostControlSignals::New());
436 if (input
.dtr
.get()) {
437 output
->has_dtr
= true;
438 output
->dtr
= *input
.dtr
;
440 if (input
.rts
.get()) {
441 output
->has_rts
= true;
442 output
->rts
= *input
.rts
;
444 return output
.Pass();
448 device::serial::ConnectionOptionsPtr
449 TypeConverter
<device::serial::ConnectionOptionsPtr
,
450 extensions::api::serial::ConnectionOptions
>::
451 Convert(const extensions::api::serial::ConnectionOptions
& input
) {
452 device::serial::ConnectionOptionsPtr
output(
453 device::serial::ConnectionOptions::New());
454 if (input
.bitrate
.get() && *input
.bitrate
> 0)
455 output
->bitrate
= *input
.bitrate
;
456 output
->data_bits
= extensions::ConvertDataBitsToMojo(input
.data_bits
);
457 output
->parity_bit
= extensions::ConvertParityBitToMojo(input
.parity_bit
);
458 output
->stop_bits
= extensions::ConvertStopBitsToMojo(input
.stop_bits
);
459 if (input
.cts_flow_control
.get()) {
460 output
->has_cts_flow_control
= true;
461 output
->cts_flow_control
= *input
.cts_flow_control
;
463 return output
.Pass();