Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / device / serial / serial_io_handler.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 "device/serial/serial_io_handler.h"
6
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
11
12 namespace device {
13
14 SerialIoHandler::SerialIoHandler(
15     scoped_refptr<base::MessageLoopProxy> file_thread_message_loop)
16     : file_thread_message_loop_(file_thread_message_loop) {
17 }
18
19 SerialIoHandler::~SerialIoHandler() {
20   DCHECK(CalledOnValidThread());
21   Close();
22 }
23
24 void SerialIoHandler::Open(const std::string& port,
25                            const OpenCompleteCallback& callback) {
26   DCHECK(CalledOnValidThread());
27   DCHECK(open_complete_.is_null());
28   open_complete_ = callback;
29   DCHECK(file_thread_message_loop_);
30   file_thread_message_loop_->PostTask(
31       FROM_HERE,
32       base::Bind(&SerialIoHandler::StartOpen,
33                  this,
34                  port,
35                  base::MessageLoopProxy::current()));
36 }
37
38 void SerialIoHandler::StartOpen(
39     const std::string& port,
40     scoped_refptr<base::MessageLoopProxy> io_message_loop) {
41   DCHECK(!open_complete_.is_null());
42   DCHECK(file_thread_message_loop_->RunsTasksOnCurrentThread());
43   DCHECK(!file_.IsValid());
44   // It's the responsibility of the API wrapper around SerialIoHandler to
45   // validate the supplied path against the set of valid port names, and
46   // it is a reasonable assumption that serial port names are ASCII.
47   DCHECK(base::IsStringASCII(port));
48   base::FilePath path(base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port)));
49   int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
50               base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE |
51               base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC |
52               base::File::FLAG_TERMINAL_DEVICE;
53   base::File file(path, flags);
54   io_message_loop->PostTask(
55       FROM_HERE,
56       base::Bind(&SerialIoHandler::FinishOpen, this, Passed(file.Pass())));
57 }
58
59 void SerialIoHandler::FinishOpen(base::File file) {
60   DCHECK(CalledOnValidThread());
61   DCHECK(!open_complete_.is_null());
62   OpenCompleteCallback callback = open_complete_;
63   open_complete_.Reset();
64
65   if (!file.IsValid()) {
66     callback.Run(false);
67     return;
68   }
69
70   file_ = file.Pass();
71
72   bool success = PostOpen();
73   if (!success)
74     Close();
75   callback.Run(success);
76 }
77
78 bool SerialIoHandler::PostOpen() {
79   return true;
80 }
81
82 void SerialIoHandler::Close() {
83   if (file_.IsValid()) {
84     DCHECK(file_thread_message_loop_);
85     file_thread_message_loop_->PostTask(
86         FROM_HERE, base::Bind(&SerialIoHandler::DoClose, Passed(file_.Pass())));
87   }
88 }
89
90 // static
91 void SerialIoHandler::DoClose(base::File port) {
92   // port closed by destructor.
93 }
94
95 void SerialIoHandler::Read(scoped_ptr<WritableBuffer> buffer) {
96   DCHECK(CalledOnValidThread());
97   DCHECK(!IsReadPending());
98   pending_read_buffer_ = buffer.Pass();
99   read_canceled_ = false;
100   AddRef();
101   ReadImpl();
102 }
103
104 void SerialIoHandler::Write(scoped_ptr<ReadOnlyBuffer> buffer) {
105   DCHECK(CalledOnValidThread());
106   DCHECK(!IsWritePending());
107   pending_write_buffer_ = buffer.Pass();
108   write_canceled_ = false;
109   AddRef();
110   WriteImpl();
111 }
112
113 void SerialIoHandler::ReadCompleted(int bytes_read,
114                                     serial::ReceiveError error) {
115   DCHECK(CalledOnValidThread());
116   DCHECK(IsReadPending());
117   scoped_ptr<WritableBuffer> pending_read_buffer = pending_read_buffer_.Pass();
118   if (error == serial::RECEIVE_ERROR_NONE) {
119     pending_read_buffer->Done(bytes_read);
120   } else {
121     pending_read_buffer->DoneWithError(bytes_read, error);
122   }
123   Release();
124 }
125
126 void SerialIoHandler::WriteCompleted(int bytes_written,
127                                      serial::SendError error) {
128   DCHECK(CalledOnValidThread());
129   DCHECK(IsWritePending());
130   scoped_ptr<ReadOnlyBuffer> pending_write_buffer =
131       pending_write_buffer_.Pass();
132   if (error == serial::SEND_ERROR_NONE) {
133     pending_write_buffer->Done(bytes_written);
134   } else {
135     pending_write_buffer->DoneWithError(bytes_written, error);
136   }
137   Release();
138 }
139
140 bool SerialIoHandler::IsReadPending() const {
141   DCHECK(CalledOnValidThread());
142   return pending_read_buffer_ != NULL;
143 }
144
145 bool SerialIoHandler::IsWritePending() const {
146   DCHECK(CalledOnValidThread());
147   return pending_write_buffer_ != NULL;
148 }
149
150 void SerialIoHandler::CancelRead(serial::ReceiveError reason) {
151   DCHECK(CalledOnValidThread());
152   if (IsReadPending() && !read_canceled_) {
153     read_canceled_ = true;
154     read_cancel_reason_ = reason;
155     CancelReadImpl();
156   }
157 }
158
159 void SerialIoHandler::CancelWrite(serial::SendError reason) {
160   DCHECK(CalledOnValidThread());
161   if (IsWritePending() && !write_canceled_) {
162     write_canceled_ = true;
163     write_cancel_reason_ = reason;
164     CancelWriteImpl();
165   }
166 }
167
168 void SerialIoHandler::QueueReadCompleted(int bytes_read,
169                                          serial::ReceiveError error) {
170   base::MessageLoop::current()->PostTask(
171       FROM_HERE,
172       base::Bind(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
173 }
174
175 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
176                                           serial::SendError error) {
177   base::MessageLoop::current()->PostTask(
178       FROM_HERE,
179       base::Bind(&SerialIoHandler::WriteCompleted, this, bytes_written, error));
180 }
181
182 }  // namespace device