Upstream version 9.38.198.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   if (error == serial::RECEIVE_ERROR_NONE) {
118     pending_read_buffer_->Done(bytes_read);
119   } else {
120     pending_read_buffer_->DoneWithError(bytes_read, error);
121   }
122   pending_read_buffer_.reset();
123   Release();
124 }
125
126 void SerialIoHandler::WriteCompleted(int bytes_written,
127                                      serial::SendError error) {
128   DCHECK(CalledOnValidThread());
129   DCHECK(IsWritePending());
130   if (error == serial::SEND_ERROR_NONE) {
131     pending_write_buffer_->Done(bytes_written);
132   } else {
133     pending_write_buffer_->DoneWithError(bytes_written, error);
134   }
135   pending_write_buffer_.reset();
136   Release();
137 }
138
139 bool SerialIoHandler::IsReadPending() const {
140   DCHECK(CalledOnValidThread());
141   return pending_read_buffer_ != NULL;
142 }
143
144 bool SerialIoHandler::IsWritePending() const {
145   DCHECK(CalledOnValidThread());
146   return pending_write_buffer_ != NULL;
147 }
148
149 void SerialIoHandler::CancelRead(serial::ReceiveError reason) {
150   DCHECK(CalledOnValidThread());
151   if (IsReadPending() && !read_canceled_) {
152     read_canceled_ = true;
153     read_cancel_reason_ = reason;
154     CancelReadImpl();
155   }
156 }
157
158 void SerialIoHandler::CancelWrite(serial::SendError reason) {
159   DCHECK(CalledOnValidThread());
160   if (IsWritePending() && !write_canceled_) {
161     write_canceled_ = true;
162     write_cancel_reason_ = reason;
163     CancelWriteImpl();
164   }
165 }
166
167 void SerialIoHandler::QueueReadCompleted(int bytes_read,
168                                          serial::ReceiveError error) {
169   base::MessageLoop::current()->PostTask(
170       FROM_HERE,
171       base::Bind(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
172 }
173
174 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
175                                           serial::SendError error) {
176   base::MessageLoop::current()->PostTask(
177       FROM_HERE,
178       base::Bind(&SerialIoHandler::WriteCompleted, this, bytes_written, error));
179 }
180
181 }  // namespace device