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"
9 #include "base/files/file_path.h"
10 #include "base/lazy_instance.h"
11 #include "extensions/browser/api/api_resource_manager.h"
12 #include "extensions/common/api/serial.h"
14 namespace extensions {
18 const int kDefaultBufferSize = 4096;
20 core_api::serial::SendError ConvertSendErrorFromMojo(
21 device::serial::SendError input) {
23 case device::serial::SEND_ERROR_NONE:
24 return core_api::serial::SEND_ERROR_NONE;
25 case device::serial::SEND_ERROR_DISCONNECTED:
26 return core_api::serial::SEND_ERROR_DISCONNECTED;
27 case device::serial::SEND_ERROR_PENDING:
28 return core_api::serial::SEND_ERROR_PENDING;
29 case device::serial::SEND_ERROR_TIMEOUT:
30 return core_api::serial::SEND_ERROR_TIMEOUT;
31 case device::serial::SEND_ERROR_SYSTEM_ERROR:
32 return core_api::serial::SEND_ERROR_SYSTEM_ERROR;
34 return core_api::serial::SEND_ERROR_NONE;
37 core_api::serial::ReceiveError ConvertReceiveErrorFromMojo(
38 device::serial::ReceiveError input) {
40 case device::serial::RECEIVE_ERROR_NONE:
41 return core_api::serial::RECEIVE_ERROR_NONE;
42 case device::serial::RECEIVE_ERROR_DISCONNECTED:
43 return core_api::serial::RECEIVE_ERROR_DISCONNECTED;
44 case device::serial::RECEIVE_ERROR_TIMEOUT:
45 return core_api::serial::RECEIVE_ERROR_TIMEOUT;
46 case device::serial::RECEIVE_ERROR_DEVICE_LOST:
47 return core_api::serial::RECEIVE_ERROR_DEVICE_LOST;
48 case device::serial::RECEIVE_ERROR_SYSTEM_ERROR:
49 return core_api::serial::RECEIVE_ERROR_SYSTEM_ERROR;
51 return core_api::serial::RECEIVE_ERROR_NONE;
54 core_api::serial::DataBits ConvertDataBitsFromMojo(
55 device::serial::DataBits input) {
57 case device::serial::DATA_BITS_NONE:
58 return core_api::serial::DATA_BITS_NONE;
59 case device::serial::DATA_BITS_SEVEN:
60 return core_api::serial::DATA_BITS_SEVEN;
61 case device::serial::DATA_BITS_EIGHT:
62 return core_api::serial::DATA_BITS_EIGHT;
64 return core_api::serial::DATA_BITS_NONE;
67 device::serial::DataBits ConvertDataBitsToMojo(
68 core_api::serial::DataBits input) {
70 case core_api::serial::DATA_BITS_NONE:
71 return device::serial::DATA_BITS_NONE;
72 case core_api::serial::DATA_BITS_SEVEN:
73 return device::serial::DATA_BITS_SEVEN;
74 case core_api::serial::DATA_BITS_EIGHT:
75 return device::serial::DATA_BITS_EIGHT;
77 return device::serial::DATA_BITS_NONE;
80 core_api::serial::ParityBit ConvertParityBitFromMojo(
81 device::serial::ParityBit input) {
83 case device::serial::PARITY_BIT_NONE:
84 return core_api::serial::PARITY_BIT_NONE;
85 case device::serial::PARITY_BIT_ODD:
86 return core_api::serial::PARITY_BIT_ODD;
87 case device::serial::PARITY_BIT_NO:
88 return core_api::serial::PARITY_BIT_NO;
89 case device::serial::PARITY_BIT_EVEN:
90 return core_api::serial::PARITY_BIT_EVEN;
92 return core_api::serial::PARITY_BIT_NONE;
95 device::serial::ParityBit ConvertParityBitToMojo(
96 core_api::serial::ParityBit input) {
98 case core_api::serial::PARITY_BIT_NONE:
99 return device::serial::PARITY_BIT_NONE;
100 case core_api::serial::PARITY_BIT_NO:
101 return device::serial::PARITY_BIT_NO;
102 case core_api::serial::PARITY_BIT_ODD:
103 return device::serial::PARITY_BIT_ODD;
104 case core_api::serial::PARITY_BIT_EVEN:
105 return device::serial::PARITY_BIT_EVEN;
107 return device::serial::PARITY_BIT_NONE;
110 core_api::serial::StopBits ConvertStopBitsFromMojo(
111 device::serial::StopBits input) {
113 case device::serial::STOP_BITS_NONE:
114 return core_api::serial::STOP_BITS_NONE;
115 case device::serial::STOP_BITS_ONE:
116 return core_api::serial::STOP_BITS_ONE;
117 case device::serial::STOP_BITS_TWO:
118 return core_api::serial::STOP_BITS_TWO;
120 return core_api::serial::STOP_BITS_NONE;
123 device::serial::StopBits ConvertStopBitsToMojo(
124 core_api::serial::StopBits input) {
126 case core_api::serial::STOP_BITS_NONE:
127 return device::serial::STOP_BITS_NONE;
128 case core_api::serial::STOP_BITS_ONE:
129 return device::serial::STOP_BITS_ONE;
130 case core_api::serial::STOP_BITS_TWO:
131 return device::serial::STOP_BITS_TWO;
133 return device::serial::STOP_BITS_NONE;
136 class SendBuffer : public device::ReadOnlyBuffer {
139 const std::string& data,
140 const base::Callback<void(int, device::serial::SendError)>& callback)
141 : data_(data), callback_(callback) {}
142 virtual ~SendBuffer() {}
143 virtual const char* GetData() OVERRIDE { return data_.c_str(); }
144 virtual uint32_t GetSize() OVERRIDE {
145 return static_cast<uint32_t>(data_.size());
147 virtual void Done(uint32_t bytes_read) OVERRIDE {
148 callback_.Run(bytes_read, device::serial::SEND_ERROR_NONE);
150 virtual void DoneWithError(uint32_t bytes_read, int32_t error) OVERRIDE {
151 callback_.Run(bytes_read, static_cast<device::serial::SendError>(error));
155 const std::string data_;
156 const base::Callback<void(int, device::serial::SendError)> callback_;
159 class ReceiveBuffer : public device::WritableBuffer {
162 scoped_refptr<net::IOBuffer> buffer,
164 const base::Callback<void(int, device::serial::ReceiveError)>& callback)
165 : buffer_(buffer), size_(size), callback_(callback) {}
166 virtual ~ReceiveBuffer() {}
167 virtual char* GetData() OVERRIDE { return buffer_->data(); }
168 virtual uint32_t GetSize() OVERRIDE { return size_; }
169 virtual void Done(uint32_t bytes_written) OVERRIDE {
170 callback_.Run(bytes_written, device::serial::RECEIVE_ERROR_NONE);
172 virtual void DoneWithError(uint32_t bytes_written, int32_t error) OVERRIDE {
173 callback_.Run(bytes_written,
174 static_cast<device::serial::ReceiveError>(error));
178 scoped_refptr<net::IOBuffer> buffer_;
179 const uint32_t size_;
180 const base::Callback<void(int, device::serial::ReceiveError)> callback_;
185 static base::LazyInstance<
186 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> > >
187 g_factory = LAZY_INSTANCE_INITIALIZER;
191 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> >*
192 ApiResourceManager<SerialConnection>::GetFactoryInstance() {
193 return g_factory.Pointer();
196 SerialConnection::SerialConnection(const std::string& port,
197 const std::string& owner_extension_id)
198 : ApiResource(owner_extension_id),
201 buffer_size_(kDefaultBufferSize),
205 io_handler_(device::SerialIoHandler::Create(
206 content::BrowserThread::GetMessageLoopProxyForThread(
207 content::BrowserThread::FILE))) {
208 DCHECK_CURRENTLY_ON(BrowserThread::IO);
211 SerialConnection::~SerialConnection() {
212 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_DISCONNECTED);
213 io_handler_->CancelWrite(device::serial::SEND_ERROR_DISCONNECTED);
216 bool SerialConnection::IsPersistent() const {
220 void SerialConnection::set_buffer_size(int buffer_size) {
221 buffer_size_ = buffer_size;
224 void SerialConnection::set_receive_timeout(int receive_timeout) {
225 receive_timeout_ = receive_timeout;
228 void SerialConnection::set_send_timeout(int send_timeout) {
229 send_timeout_ = send_timeout;
232 void SerialConnection::set_paused(bool paused) {
235 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_NONE);
239 void SerialConnection::Open(const OpenCompleteCallback& callback) {
240 DCHECK_CURRENTLY_ON(BrowserThread::IO);
241 io_handler_->Open(port_, callback);
244 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
245 DCHECK_CURRENTLY_ON(BrowserThread::IO);
246 if (!receive_complete_.is_null())
248 receive_complete_ = callback;
249 receive_buffer_ = new net::IOBuffer(buffer_size_);
250 io_handler_->Read(scoped_ptr<device::WritableBuffer>(new ReceiveBuffer(
253 base::Bind(&SerialConnection::OnAsyncReadComplete, AsWeakPtr()))));
254 receive_timeout_task_.reset();
255 if (receive_timeout_ > 0) {
256 receive_timeout_task_.reset(new TimeoutTask(
257 base::Bind(&SerialConnection::OnReceiveTimeout, AsWeakPtr()),
258 base::TimeDelta::FromMilliseconds(receive_timeout_)));
263 bool SerialConnection::Send(const std::string& data,
264 const SendCompleteCallback& callback) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO);
266 if (!send_complete_.is_null())
268 send_complete_ = callback;
269 io_handler_->Write(scoped_ptr<device::ReadOnlyBuffer>(new SendBuffer(
270 data, base::Bind(&SerialConnection::OnAsyncWriteComplete, AsWeakPtr()))));
271 send_timeout_task_.reset();
272 if (send_timeout_ > 0) {
273 send_timeout_task_.reset(new TimeoutTask(
274 base::Bind(&SerialConnection::OnSendTimeout, AsWeakPtr()),
275 base::TimeDelta::FromMilliseconds(send_timeout_)));
280 bool SerialConnection::Configure(
281 const core_api::serial::ConnectionOptions& options) {
282 DCHECK_CURRENTLY_ON(BrowserThread::IO);
283 if (options.persistent.get())
284 set_persistent(*options.persistent);
285 if (options.name.get())
286 set_name(*options.name);
287 if (options.buffer_size.get())
288 set_buffer_size(*options.buffer_size);
289 if (options.receive_timeout.get())
290 set_receive_timeout(*options.receive_timeout);
291 if (options.send_timeout.get())
292 set_send_timeout(*options.send_timeout);
293 bool success = io_handler_->ConfigurePort(
294 *device::serial::ConnectionOptions::From(options));
295 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_NONE);
299 void SerialConnection::SetIoHandlerForTest(
300 scoped_refptr<device::SerialIoHandler> handler) {
301 io_handler_ = handler;
304 bool SerialConnection::GetInfo(core_api::serial::ConnectionInfo* info) const {
305 DCHECK_CURRENTLY_ON(BrowserThread::IO);
306 info->paused = paused_;
307 info->persistent = persistent_;
309 info->buffer_size = buffer_size_;
310 info->receive_timeout = receive_timeout_;
311 info->send_timeout = send_timeout_;
312 device::serial::ConnectionInfoPtr port_info = io_handler_->GetPortInfo();
316 info->bitrate.reset(new int(port_info->bitrate));
317 info->data_bits = ConvertDataBitsFromMojo(port_info->data_bits);
318 info->parity_bit = ConvertParityBitFromMojo(port_info->parity_bit);
319 info->stop_bits = ConvertStopBitsFromMojo(port_info->stop_bits);
320 info->cts_flow_control.reset(new bool(port_info->cts_flow_control));
324 bool SerialConnection::Flush() const {
325 return io_handler_->Flush();
328 bool SerialConnection::GetControlSignals(
329 core_api::serial::DeviceControlSignals* control_signals) const {
330 device::serial::DeviceControlSignalsPtr signals =
331 io_handler_->GetControlSignals();
335 control_signals->dcd = signals->dcd;
336 control_signals->cts = signals->cts;
337 control_signals->ri = signals->ri;
338 control_signals->dsr = signals->dsr;
342 bool SerialConnection::SetControlSignals(
343 const core_api::serial::HostControlSignals& control_signals) {
344 return io_handler_->SetControlSignals(
345 *device::serial::HostControlSignals::From(control_signals));
348 void SerialConnection::OnReceiveTimeout() {
349 DCHECK_CURRENTLY_ON(BrowserThread::IO);
350 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_TIMEOUT);
353 void SerialConnection::OnSendTimeout() {
354 DCHECK_CURRENTLY_ON(BrowserThread::IO);
355 io_handler_->CancelWrite(device::serial::SEND_ERROR_TIMEOUT);
358 void SerialConnection::OnAsyncReadComplete(int bytes_read,
359 device::serial::ReceiveError error) {
360 DCHECK_CURRENTLY_ON(BrowserThread::IO);
361 DCHECK(!receive_complete_.is_null());
362 ReceiveCompleteCallback callback = receive_complete_;
363 receive_complete_.Reset();
364 receive_timeout_task_.reset();
365 callback.Run(std::string(receive_buffer_->data(), bytes_read),
366 ConvertReceiveErrorFromMojo(error));
367 receive_buffer_ = NULL;
370 void SerialConnection::OnAsyncWriteComplete(int bytes_sent,
371 device::serial::SendError error) {
372 DCHECK_CURRENTLY_ON(BrowserThread::IO);
373 DCHECK(!send_complete_.is_null());
374 SendCompleteCallback callback = send_complete_;
375 send_complete_.Reset();
376 send_timeout_task_.reset();
377 callback.Run(bytes_sent, ConvertSendErrorFromMojo(error));
380 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure& closure,
381 const base::TimeDelta& delay)
382 : weak_factory_(this), closure_(closure), delay_(delay) {
383 base::MessageLoop::current()->PostDelayedTask(
385 base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()),
389 SerialConnection::TimeoutTask::~TimeoutTask() {
392 void SerialConnection::TimeoutTask::Run() const {
396 } // namespace extensions
401 device::serial::HostControlSignalsPtr
402 TypeConverter<device::serial::HostControlSignalsPtr,
403 extensions::core_api::serial::HostControlSignals>::
404 Convert(const extensions::core_api::serial::HostControlSignals& input) {
405 device::serial::HostControlSignalsPtr output(
406 device::serial::HostControlSignals::New());
407 if (input.dtr.get()) {
408 output->has_dtr = true;
409 output->dtr = *input.dtr;
411 if (input.rts.get()) {
412 output->has_rts = true;
413 output->rts = *input.rts;
415 return output.Pass();
419 device::serial::ConnectionOptionsPtr
420 TypeConverter<device::serial::ConnectionOptionsPtr,
421 extensions::core_api::serial::ConnectionOptions>::
422 Convert(const extensions::core_api::serial::ConnectionOptions& input) {
423 device::serial::ConnectionOptionsPtr output(
424 device::serial::ConnectionOptions::New());
425 if (input.bitrate.get() && *input.bitrate > 0)
426 output->bitrate = *input.bitrate;
427 output->data_bits = extensions::ConvertDataBitsToMojo(input.data_bits);
428 output->parity_bit = extensions::ConvertParityBitToMojo(input.parity_bit);
429 output->stop_bits = extensions::ConvertStopBitsToMojo(input.stop_bits);
430 if (input.cts_flow_control.get()) {
431 output->has_cts_flow_control = true;
432 output->cts_flow_control = *input.cts_flow_control;
434 return output.Pass();