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 core_api::serial::SendError
ConvertSendErrorFromMojo(
24 device::serial::SendError input
) {
26 case device::serial::SEND_ERROR_NONE
:
27 return core_api::serial::SEND_ERROR_NONE
;
28 case device::serial::SEND_ERROR_DISCONNECTED
:
29 return core_api::serial::SEND_ERROR_DISCONNECTED
;
30 case device::serial::SEND_ERROR_PENDING
:
31 return core_api::serial::SEND_ERROR_PENDING
;
32 case device::serial::SEND_ERROR_TIMEOUT
:
33 return core_api::serial::SEND_ERROR_TIMEOUT
;
34 case device::serial::SEND_ERROR_SYSTEM_ERROR
:
35 return core_api::serial::SEND_ERROR_SYSTEM_ERROR
;
37 return core_api::serial::SEND_ERROR_NONE
;
40 core_api::serial::ReceiveError
ConvertReceiveErrorFromMojo(
41 device::serial::ReceiveError input
) {
43 case device::serial::RECEIVE_ERROR_NONE
:
44 return core_api::serial::RECEIVE_ERROR_NONE
;
45 case device::serial::RECEIVE_ERROR_DISCONNECTED
:
46 return core_api::serial::RECEIVE_ERROR_DISCONNECTED
;
47 case device::serial::RECEIVE_ERROR_TIMEOUT
:
48 return core_api::serial::RECEIVE_ERROR_TIMEOUT
;
49 case device::serial::RECEIVE_ERROR_DEVICE_LOST
:
50 return core_api::serial::RECEIVE_ERROR_DEVICE_LOST
;
51 case device::serial::RECEIVE_ERROR_BREAK
:
52 return core_api::serial::RECEIVE_ERROR_BREAK
;
53 case device::serial::RECEIVE_ERROR_FRAME_ERROR
:
54 return core_api::serial::RECEIVE_ERROR_FRAME_ERROR
;
55 case device::serial::RECEIVE_ERROR_OVERRUN
:
56 return core_api::serial::RECEIVE_ERROR_OVERRUN
;
57 case device::serial::RECEIVE_ERROR_BUFFER_OVERFLOW
:
58 return core_api::serial::RECEIVE_ERROR_BUFFER_OVERFLOW
;
59 case device::serial::RECEIVE_ERROR_PARITY_ERROR
:
60 return core_api::serial::RECEIVE_ERROR_PARITY_ERROR
;
61 case device::serial::RECEIVE_ERROR_SYSTEM_ERROR
:
62 return core_api::serial::RECEIVE_ERROR_SYSTEM_ERROR
;
64 return core_api::serial::RECEIVE_ERROR_NONE
;
67 core_api::serial::DataBits
ConvertDataBitsFromMojo(
68 device::serial::DataBits input
) {
70 case device::serial::DATA_BITS_NONE
:
71 return core_api::serial::DATA_BITS_NONE
;
72 case device::serial::DATA_BITS_SEVEN
:
73 return core_api::serial::DATA_BITS_SEVEN
;
74 case device::serial::DATA_BITS_EIGHT
:
75 return core_api::serial::DATA_BITS_EIGHT
;
77 return core_api::serial::DATA_BITS_NONE
;
80 device::serial::DataBits
ConvertDataBitsToMojo(
81 core_api::serial::DataBits input
) {
83 case core_api::serial::DATA_BITS_NONE
:
84 return device::serial::DATA_BITS_NONE
;
85 case core_api::serial::DATA_BITS_SEVEN
:
86 return device::serial::DATA_BITS_SEVEN
;
87 case core_api::serial::DATA_BITS_EIGHT
:
88 return device::serial::DATA_BITS_EIGHT
;
90 return device::serial::DATA_BITS_NONE
;
93 core_api::serial::ParityBit
ConvertParityBitFromMojo(
94 device::serial::ParityBit input
) {
96 case device::serial::PARITY_BIT_NONE
:
97 return core_api::serial::PARITY_BIT_NONE
;
98 case device::serial::PARITY_BIT_ODD
:
99 return core_api::serial::PARITY_BIT_ODD
;
100 case device::serial::PARITY_BIT_NO
:
101 return core_api::serial::PARITY_BIT_NO
;
102 case device::serial::PARITY_BIT_EVEN
:
103 return core_api::serial::PARITY_BIT_EVEN
;
105 return core_api::serial::PARITY_BIT_NONE
;
108 device::serial::ParityBit
ConvertParityBitToMojo(
109 core_api::serial::ParityBit input
) {
111 case core_api::serial::PARITY_BIT_NONE
:
112 return device::serial::PARITY_BIT_NONE
;
113 case core_api::serial::PARITY_BIT_NO
:
114 return device::serial::PARITY_BIT_NO
;
115 case core_api::serial::PARITY_BIT_ODD
:
116 return device::serial::PARITY_BIT_ODD
;
117 case core_api::serial::PARITY_BIT_EVEN
:
118 return device::serial::PARITY_BIT_EVEN
;
120 return device::serial::PARITY_BIT_NONE
;
123 core_api::serial::StopBits
ConvertStopBitsFromMojo(
124 device::serial::StopBits input
) {
126 case device::serial::STOP_BITS_NONE
:
127 return core_api::serial::STOP_BITS_NONE
;
128 case device::serial::STOP_BITS_ONE
:
129 return core_api::serial::STOP_BITS_ONE
;
130 case device::serial::STOP_BITS_TWO
:
131 return core_api::serial::STOP_BITS_TWO
;
133 return core_api::serial::STOP_BITS_NONE
;
136 device::serial::StopBits
ConvertStopBitsToMojo(
137 core_api::serial::StopBits input
) {
139 case core_api::serial::STOP_BITS_NONE
:
140 return device::serial::STOP_BITS_NONE
;
141 case core_api::serial::STOP_BITS_ONE
:
142 return device::serial::STOP_BITS_ONE
;
143 case core_api::serial::STOP_BITS_TWO
:
144 return device::serial::STOP_BITS_TWO
;
146 return device::serial::STOP_BITS_NONE
;
149 class SendBuffer
: public device::ReadOnlyBuffer
{
152 const std::vector
<char>& data
,
153 const base::Callback
<void(int, device::serial::SendError
)>& callback
)
154 : data_(data
), callback_(callback
) {}
155 ~SendBuffer() override
{}
156 const char* GetData() override
{ return vector_as_array(&data_
); }
157 uint32_t GetSize() override
{ return static_cast<uint32_t>(data_
.size()); }
158 void Done(uint32_t bytes_read
) override
{
159 callback_
.Run(bytes_read
, device::serial::SEND_ERROR_NONE
);
161 void DoneWithError(uint32_t bytes_read
, int32_t error
) override
{
162 callback_
.Run(bytes_read
, static_cast<device::serial::SendError
>(error
));
166 const std::vector
<char> data_
;
167 const base::Callback
<void(int, device::serial::SendError
)> callback_
;
170 class ReceiveBuffer
: public device::WritableBuffer
{
173 scoped_refptr
<net::IOBuffer
> buffer
,
175 const base::Callback
<void(int, device::serial::ReceiveError
)>& callback
)
176 : buffer_(buffer
), size_(size
), callback_(callback
) {}
177 ~ReceiveBuffer() override
{}
178 char* GetData() override
{ return buffer_
->data(); }
179 uint32_t GetSize() override
{ return size_
; }
180 void Done(uint32_t bytes_written
) override
{
181 callback_
.Run(bytes_written
, device::serial::RECEIVE_ERROR_NONE
);
183 void DoneWithError(uint32_t bytes_written
, int32_t error
) override
{
184 callback_
.Run(bytes_written
,
185 static_cast<device::serial::ReceiveError
>(error
));
189 scoped_refptr
<net::IOBuffer
> buffer_
;
190 const uint32_t size_
;
191 const base::Callback
<void(int, device::serial::ReceiveError
)> callback_
;
196 static base::LazyInstance
<
197 BrowserContextKeyedAPIFactory
<ApiResourceManager
<SerialConnection
> > >
198 g_factory
= LAZY_INSTANCE_INITIALIZER
;
202 BrowserContextKeyedAPIFactory
<ApiResourceManager
<SerialConnection
> >*
203 ApiResourceManager
<SerialConnection
>::GetFactoryInstance() {
204 return g_factory
.Pointer();
207 SerialConnection::SerialConnection(const std::string
& port
,
208 const std::string
& owner_extension_id
)
209 : ApiResource(owner_extension_id
),
212 buffer_size_(kDefaultBufferSize
),
216 io_handler_(device::SerialIoHandler::Create(
217 content::BrowserThread::GetMessageLoopProxyForThread(
218 content::BrowserThread::FILE),
219 content::BrowserThread::GetMessageLoopProxyForThread(
220 content::BrowserThread::UI
))) {
221 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
224 SerialConnection::~SerialConnection() {
225 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_DISCONNECTED
);
226 io_handler_
->CancelWrite(device::serial::SEND_ERROR_DISCONNECTED
);
229 bool SerialConnection::IsPersistent() const {
233 void SerialConnection::set_buffer_size(int buffer_size
) {
234 buffer_size_
= buffer_size
;
237 void SerialConnection::set_receive_timeout(int receive_timeout
) {
238 receive_timeout_
= receive_timeout
;
241 void SerialConnection::set_send_timeout(int send_timeout
) {
242 send_timeout_
= send_timeout
;
245 void SerialConnection::set_paused(bool paused
) {
248 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_NONE
);
252 void SerialConnection::Open(const core_api::serial::ConnectionOptions
& options
,
253 const OpenCompleteCallback
& callback
) {
254 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
255 if (options
.persistent
.get())
256 set_persistent(*options
.persistent
);
257 if (options
.name
.get())
258 set_name(*options
.name
);
259 if (options
.buffer_size
.get())
260 set_buffer_size(*options
.buffer_size
);
261 if (options
.receive_timeout
.get())
262 set_receive_timeout(*options
.receive_timeout
);
263 if (options
.send_timeout
.get())
264 set_send_timeout(*options
.send_timeout
);
265 io_handler_
->Open(port_
, *device::serial::ConnectionOptions::From(options
),
269 bool SerialConnection::Receive(const ReceiveCompleteCallback
& callback
) {
270 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
271 if (!receive_complete_
.is_null())
273 receive_complete_
= callback
;
274 receive_buffer_
= new net::IOBuffer(buffer_size_
);
275 io_handler_
->Read(scoped_ptr
<device::WritableBuffer
>(new ReceiveBuffer(
278 base::Bind(&SerialConnection::OnAsyncReadComplete
, AsWeakPtr()))));
279 receive_timeout_task_
.reset();
280 if (receive_timeout_
> 0) {
281 receive_timeout_task_
.reset(new TimeoutTask(
282 base::Bind(&SerialConnection::OnReceiveTimeout
, AsWeakPtr()),
283 base::TimeDelta::FromMilliseconds(receive_timeout_
)));
288 bool SerialConnection::Send(const std::vector
<char>& data
,
289 const SendCompleteCallback
& callback
) {
290 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
291 if (!send_complete_
.is_null())
293 send_complete_
= callback
;
294 io_handler_
->Write(scoped_ptr
<device::ReadOnlyBuffer
>(new SendBuffer(
295 data
, base::Bind(&SerialConnection::OnAsyncWriteComplete
, AsWeakPtr()))));
296 send_timeout_task_
.reset();
297 if (send_timeout_
> 0) {
298 send_timeout_task_
.reset(new TimeoutTask(
299 base::Bind(&SerialConnection::OnSendTimeout
, AsWeakPtr()),
300 base::TimeDelta::FromMilliseconds(send_timeout_
)));
305 bool SerialConnection::Configure(
306 const core_api::serial::ConnectionOptions
& options
) {
307 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
308 if (options
.persistent
.get())
309 set_persistent(*options
.persistent
);
310 if (options
.name
.get())
311 set_name(*options
.name
);
312 if (options
.buffer_size
.get())
313 set_buffer_size(*options
.buffer_size
);
314 if (options
.receive_timeout
.get())
315 set_receive_timeout(*options
.receive_timeout
);
316 if (options
.send_timeout
.get())
317 set_send_timeout(*options
.send_timeout
);
318 bool success
= io_handler_
->ConfigurePort(
319 *device::serial::ConnectionOptions::From(options
));
320 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_NONE
);
324 void SerialConnection::SetIoHandlerForTest(
325 scoped_refptr
<device::SerialIoHandler
> handler
) {
326 io_handler_
= handler
;
329 bool SerialConnection::GetInfo(core_api::serial::ConnectionInfo
* info
) const {
330 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
331 info
->paused
= paused_
;
332 info
->persistent
= persistent_
;
334 info
->buffer_size
= buffer_size_
;
335 info
->receive_timeout
= receive_timeout_
;
336 info
->send_timeout
= send_timeout_
;
337 device::serial::ConnectionInfoPtr port_info
= io_handler_
->GetPortInfo();
341 info
->bitrate
.reset(new int(port_info
->bitrate
));
342 info
->data_bits
= ConvertDataBitsFromMojo(port_info
->data_bits
);
343 info
->parity_bit
= ConvertParityBitFromMojo(port_info
->parity_bit
);
344 info
->stop_bits
= ConvertStopBitsFromMojo(port_info
->stop_bits
);
345 info
->cts_flow_control
.reset(new bool(port_info
->cts_flow_control
));
349 bool SerialConnection::Flush() const {
350 return io_handler_
->Flush();
353 bool SerialConnection::GetControlSignals(
354 core_api::serial::DeviceControlSignals
* control_signals
) const {
355 device::serial::DeviceControlSignalsPtr signals
=
356 io_handler_
->GetControlSignals();
360 control_signals
->dcd
= signals
->dcd
;
361 control_signals
->cts
= signals
->cts
;
362 control_signals
->ri
= signals
->ri
;
363 control_signals
->dsr
= signals
->dsr
;
367 bool SerialConnection::SetControlSignals(
368 const core_api::serial::HostControlSignals
& control_signals
) {
369 return io_handler_
->SetControlSignals(
370 *device::serial::HostControlSignals::From(control_signals
));
373 bool SerialConnection::SetBreak() {
374 return io_handler_
->SetBreak();
377 bool SerialConnection::ClearBreak() {
378 return io_handler_
->ClearBreak();
381 void SerialConnection::OnReceiveTimeout() {
382 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
383 io_handler_
->CancelRead(device::serial::RECEIVE_ERROR_TIMEOUT
);
386 void SerialConnection::OnSendTimeout() {
387 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
388 io_handler_
->CancelWrite(device::serial::SEND_ERROR_TIMEOUT
);
391 void SerialConnection::OnAsyncReadComplete(int bytes_read
,
392 device::serial::ReceiveError error
) {
393 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
394 DCHECK(!receive_complete_
.is_null());
395 ReceiveCompleteCallback callback
= receive_complete_
;
396 receive_complete_
.Reset();
397 receive_timeout_task_
.reset();
398 callback
.Run(std::vector
<char>(receive_buffer_
->data(),
399 receive_buffer_
->data() + bytes_read
),
400 ConvertReceiveErrorFromMojo(error
));
401 receive_buffer_
= NULL
;
404 void SerialConnection::OnAsyncWriteComplete(int bytes_sent
,
405 device::serial::SendError error
) {
406 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
407 DCHECK(!send_complete_
.is_null());
408 SendCompleteCallback callback
= send_complete_
;
409 send_complete_
.Reset();
410 send_timeout_task_
.reset();
411 callback
.Run(bytes_sent
, ConvertSendErrorFromMojo(error
));
414 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure
& closure
,
415 const base::TimeDelta
& delay
)
416 : closure_(closure
), delay_(delay
), weak_factory_(this) {
417 base::MessageLoop::current()->PostDelayedTask(
419 base::Bind(&TimeoutTask::Run
, weak_factory_
.GetWeakPtr()),
423 SerialConnection::TimeoutTask::~TimeoutTask() {
426 void SerialConnection::TimeoutTask::Run() const {
430 } // namespace extensions
435 device::serial::HostControlSignalsPtr
436 TypeConverter
<device::serial::HostControlSignalsPtr
,
437 extensions::core_api::serial::HostControlSignals
>::
438 Convert(const extensions::core_api::serial::HostControlSignals
& input
) {
439 device::serial::HostControlSignalsPtr
output(
440 device::serial::HostControlSignals::New());
441 if (input
.dtr
.get()) {
442 output
->has_dtr
= true;
443 output
->dtr
= *input
.dtr
;
445 if (input
.rts
.get()) {
446 output
->has_rts
= true;
447 output
->rts
= *input
.rts
;
449 return output
.Pass();
453 device::serial::ConnectionOptionsPtr
454 TypeConverter
<device::serial::ConnectionOptionsPtr
,
455 extensions::core_api::serial::ConnectionOptions
>::
456 Convert(const extensions::core_api::serial::ConnectionOptions
& input
) {
457 device::serial::ConnectionOptionsPtr
output(
458 device::serial::ConnectionOptions::New());
459 if (input
.bitrate
.get() && *input
.bitrate
> 0)
460 output
->bitrate
= *input
.bitrate
;
461 output
->data_bits
= extensions::ConvertDataBitsToMojo(input
.data_bits
);
462 output
->parity_bit
= extensions::ConvertParityBitToMojo(input
.parity_bit
);
463 output
->stop_bits
= extensions::ConvertStopBitsToMojo(input
.stop_bits
);
464 if (input
.cts_flow_control
.get()) {
465 output
->has_cts_flow_control
= true;
466 output
->cts_flow_control
= *input
.cts_flow_control
;
468 return output
.Pass();