Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / api / serial / serial_connection.cc
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.
4
5 #include "extensions/browser/api/serial/serial_connection.h"
6
7 #include <string>
8
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"
13
14 namespace extensions {
15
16 namespace {
17
18 const int kDefaultBufferSize = 4096;
19
20 core_api::serial::SendError ConvertSendErrorFromMojo(
21     device::serial::SendError input) {
22   switch (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;
33   }
34   return core_api::serial::SEND_ERROR_NONE;
35 }
36
37 core_api::serial::ReceiveError ConvertReceiveErrorFromMojo(
38     device::serial::ReceiveError input) {
39   switch (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;
50   }
51   return core_api::serial::RECEIVE_ERROR_NONE;
52 }
53
54 core_api::serial::DataBits ConvertDataBitsFromMojo(
55     device::serial::DataBits input) {
56   switch (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;
63   }
64   return core_api::serial::DATA_BITS_NONE;
65 }
66
67 device::serial::DataBits ConvertDataBitsToMojo(
68     core_api::serial::DataBits input) {
69   switch (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;
76   }
77   return device::serial::DATA_BITS_NONE;
78 }
79
80 core_api::serial::ParityBit ConvertParityBitFromMojo(
81     device::serial::ParityBit input) {
82   switch (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;
91   }
92   return core_api::serial::PARITY_BIT_NONE;
93 }
94
95 device::serial::ParityBit ConvertParityBitToMojo(
96     core_api::serial::ParityBit input) {
97   switch (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;
106   }
107   return device::serial::PARITY_BIT_NONE;
108 }
109
110 core_api::serial::StopBits ConvertStopBitsFromMojo(
111     device::serial::StopBits input) {
112   switch (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;
119   }
120   return core_api::serial::STOP_BITS_NONE;
121 }
122
123 device::serial::StopBits ConvertStopBitsToMojo(
124     core_api::serial::StopBits input) {
125   switch (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;
132   }
133   return device::serial::STOP_BITS_NONE;
134 }
135
136 class SendBuffer : public device::ReadOnlyBuffer {
137  public:
138   SendBuffer(
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());
146   }
147   virtual void Done(uint32_t bytes_read) OVERRIDE {
148     callback_.Run(bytes_read, device::serial::SEND_ERROR_NONE);
149   }
150   virtual void DoneWithError(uint32_t bytes_read, int32_t error) OVERRIDE {
151     callback_.Run(bytes_read, static_cast<device::serial::SendError>(error));
152   }
153
154  private:
155   const std::string data_;
156   const base::Callback<void(int, device::serial::SendError)> callback_;
157 };
158
159 class ReceiveBuffer : public device::WritableBuffer {
160  public:
161   ReceiveBuffer(
162       scoped_refptr<net::IOBuffer> buffer,
163       uint32_t size,
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);
171   }
172   virtual void DoneWithError(uint32_t bytes_written, int32_t error) OVERRIDE {
173     callback_.Run(bytes_written,
174                   static_cast<device::serial::ReceiveError>(error));
175   }
176
177  private:
178   scoped_refptr<net::IOBuffer> buffer_;
179   const uint32_t size_;
180   const base::Callback<void(int, device::serial::ReceiveError)> callback_;
181 };
182
183 }  // namespace
184
185 static base::LazyInstance<
186     BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> > >
187     g_factory = LAZY_INSTANCE_INITIALIZER;
188
189 // static
190 template <>
191 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> >*
192 ApiResourceManager<SerialConnection>::GetFactoryInstance() {
193   return g_factory.Pointer();
194 }
195
196 SerialConnection::SerialConnection(const std::string& port,
197                                    const std::string& owner_extension_id)
198     : ApiResource(owner_extension_id),
199       port_(port),
200       persistent_(false),
201       buffer_size_(kDefaultBufferSize),
202       receive_timeout_(0),
203       send_timeout_(0),
204       paused_(false),
205       io_handler_(device::SerialIoHandler::Create(
206           content::BrowserThread::GetMessageLoopProxyForThread(
207               content::BrowserThread::FILE))) {
208   DCHECK_CURRENTLY_ON(BrowserThread::IO);
209 }
210
211 SerialConnection::~SerialConnection() {
212   io_handler_->CancelRead(device::serial::RECEIVE_ERROR_DISCONNECTED);
213   io_handler_->CancelWrite(device::serial::SEND_ERROR_DISCONNECTED);
214 }
215
216 bool SerialConnection::IsPersistent() const {
217   return persistent();
218 }
219
220 void SerialConnection::set_buffer_size(int buffer_size) {
221   buffer_size_ = buffer_size;
222 }
223
224 void SerialConnection::set_receive_timeout(int receive_timeout) {
225   receive_timeout_ = receive_timeout;
226 }
227
228 void SerialConnection::set_send_timeout(int send_timeout) {
229   send_timeout_ = send_timeout;
230 }
231
232 void SerialConnection::set_paused(bool paused) {
233   paused_ = paused;
234   if (paused) {
235     io_handler_->CancelRead(device::serial::RECEIVE_ERROR_NONE);
236   }
237 }
238
239 void SerialConnection::Open(const OpenCompleteCallback& callback) {
240   DCHECK_CURRENTLY_ON(BrowserThread::IO);
241   io_handler_->Open(port_, callback);
242 }
243
244 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
245   DCHECK_CURRENTLY_ON(BrowserThread::IO);
246   if (!receive_complete_.is_null())
247     return false;
248   receive_complete_ = callback;
249   receive_buffer_ = new net::IOBuffer(buffer_size_);
250   io_handler_->Read(scoped_ptr<device::WritableBuffer>(new ReceiveBuffer(
251       receive_buffer_,
252       buffer_size_,
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_)));
259   }
260   return true;
261 }
262
263 bool SerialConnection::Send(const std::string& data,
264                             const SendCompleteCallback& callback) {
265   DCHECK_CURRENTLY_ON(BrowserThread::IO);
266   if (!send_complete_.is_null())
267     return false;
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_)));
276   }
277   return true;
278 }
279
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);
296   return success;
297 }
298
299 void SerialConnection::SetIoHandlerForTest(
300     scoped_refptr<device::SerialIoHandler> handler) {
301   io_handler_ = handler;
302 }
303
304 bool SerialConnection::GetInfo(core_api::serial::ConnectionInfo* info) const {
305   DCHECK_CURRENTLY_ON(BrowserThread::IO);
306   info->paused = paused_;
307   info->persistent = persistent_;
308   info->name = name_;
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();
313   if (!port_info)
314     return false;
315
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));
321   return true;
322 }
323
324 bool SerialConnection::Flush() const {
325   return io_handler_->Flush();
326 }
327
328 bool SerialConnection::GetControlSignals(
329     core_api::serial::DeviceControlSignals* control_signals) const {
330   device::serial::DeviceControlSignalsPtr signals =
331       io_handler_->GetControlSignals();
332   if (!signals)
333     return false;
334
335   control_signals->dcd = signals->dcd;
336   control_signals->cts = signals->cts;
337   control_signals->ri = signals->ri;
338   control_signals->dsr = signals->dsr;
339   return true;
340 }
341
342 bool SerialConnection::SetControlSignals(
343     const core_api::serial::HostControlSignals& control_signals) {
344   return io_handler_->SetControlSignals(
345       *device::serial::HostControlSignals::From(control_signals));
346 }
347
348 void SerialConnection::OnReceiveTimeout() {
349   DCHECK_CURRENTLY_ON(BrowserThread::IO);
350   io_handler_->CancelRead(device::serial::RECEIVE_ERROR_TIMEOUT);
351 }
352
353 void SerialConnection::OnSendTimeout() {
354   DCHECK_CURRENTLY_ON(BrowserThread::IO);
355   io_handler_->CancelWrite(device::serial::SEND_ERROR_TIMEOUT);
356 }
357
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;
368 }
369
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));
378 }
379
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(
384       FROM_HERE,
385       base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()),
386       delay_);
387 }
388
389 SerialConnection::TimeoutTask::~TimeoutTask() {
390 }
391
392 void SerialConnection::TimeoutTask::Run() const {
393   closure_.Run();
394 }
395
396 }  // namespace extensions
397
398 namespace mojo {
399
400 // static
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;
410   }
411   if (input.rts.get()) {
412     output->has_rts = true;
413     output->rts = *input.rts;
414   }
415   return output.Pass();
416 }
417
418 // static
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;
433   }
434   return output.Pass();
435 }
436
437 }  // namespace mojo