Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / browser / api / serial / serial_connection.cc
blob65b27a125e245f8d18938085fbb13fa642008eb2
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"
7 #include <string>
8 #include <vector>
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 {
19 namespace {
21 const int kDefaultBufferSize = 4096;
23 api::serial::SendError ConvertSendErrorFromMojo(
24 device::serial::SendError input) {
25 switch (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) {
42 switch (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) {
68 switch (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) {
80 switch (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) {
93 switch (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) {
107 switch (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) {
121 switch (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) {
133 switch (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 {
145 public:
146 SendBuffer(
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));
160 private:
161 const std::vector<char> data_;
162 const base::Callback<void(int, device::serial::SendError)> callback_;
165 class ReceiveBuffer : public device::WritableBuffer {
166 public:
167 ReceiveBuffer(
168 scoped_refptr<net::IOBuffer> buffer,
169 uint32_t size,
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));
183 private:
184 scoped_refptr<net::IOBuffer> buffer_;
185 const uint32_t size_;
186 const base::Callback<void(int, device::serial::ReceiveError)> callback_;
189 } // namespace
191 static base::LazyInstance<
192 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> > >
193 g_factory = LAZY_INSTANCE_INITIALIZER;
195 // static
196 template <>
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),
205 port_(port),
206 persistent_(false),
207 buffer_size_(kDefaultBufferSize),
208 receive_timeout_(0),
209 send_timeout_(0),
210 paused_(false),
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 {
225 return persistent();
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) {
241 paused_ = paused;
242 if (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),
261 callback);
264 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
265 DCHECK_CURRENTLY_ON(BrowserThread::IO);
266 if (!receive_complete_.is_null())
267 return false;
268 receive_complete_ = callback;
269 receive_buffer_ = new net::IOBuffer(buffer_size_);
270 io_handler_->Read(scoped_ptr<device::WritableBuffer>(new ReceiveBuffer(
271 receive_buffer_,
272 buffer_size_,
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_)));
280 return true;
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())
287 return false;
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_)));
297 return true;
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);
316 return success;
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_;
328 info->name = name_;
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();
333 if (!port_info)
334 return false;
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));
341 return true;
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();
352 if (!signals)
353 return false;
355 control_signals->dcd = signals->dcd;
356 control_signals->cts = signals->cts;
357 control_signals->ri = signals->ri;
358 control_signals->dsr = signals->dsr;
359 return true;
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(
413 FROM_HERE,
414 base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()),
415 delay_);
418 SerialConnection::TimeoutTask::~TimeoutTask() {
421 void SerialConnection::TimeoutTask::Run() const {
422 closure_.Run();
425 } // namespace extensions
427 namespace mojo {
429 // static
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();
447 // static
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();
466 } // namespace mojo