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 "device/serial/serial_io_handler.h"
8 #include "base/files/file_path.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_util.h"
14 SerialIoHandler::SerialIoHandler(
15 scoped_refptr
<base::MessageLoopProxy
> file_thread_message_loop
,
16 scoped_refptr
<base::MessageLoopProxy
> ui_thread_message_loop
)
17 : file_thread_message_loop_(file_thread_message_loop
),
18 ui_thread_message_loop_(ui_thread_message_loop
) {
21 SerialIoHandler::~SerialIoHandler() {
22 DCHECK(CalledOnValidThread());
26 void SerialIoHandler::Open(const std::string
& port
,
27 const OpenCompleteCallback
& callback
) {
28 DCHECK(CalledOnValidThread());
29 DCHECK(open_complete_
.is_null());
30 open_complete_
= callback
;
31 DCHECK(file_thread_message_loop_
.get());
32 DCHECK(ui_thread_message_loop_
.get());
33 RequestAccess(port
, file_thread_message_loop_
, ui_thread_message_loop_
);
36 void SerialIoHandler::RequestAccess(
37 const std::string
& port
,
38 scoped_refptr
<base::MessageLoopProxy
> file_message_loop
,
39 scoped_refptr
<base::MessageLoopProxy
> ui_message_loop
) {
40 OnRequestAccessComplete(port
, true /* success */);
43 void SerialIoHandler::OnRequestAccessComplete(const std::string
& port
,
45 DCHECK(CalledOnValidThread());
47 DCHECK(file_thread_message_loop_
.get());
48 file_thread_message_loop_
->PostTask(
50 base::Bind(&SerialIoHandler::StartOpen
,
53 base::MessageLoopProxy::current()));
56 DCHECK(!open_complete_
.is_null());
57 OpenCompleteCallback callback
= open_complete_
;
58 open_complete_
.Reset();
64 void SerialIoHandler::StartOpen(
65 const std::string
& port
,
66 scoped_refptr
<base::MessageLoopProxy
> io_message_loop
) {
67 DCHECK(!open_complete_
.is_null());
68 DCHECK(file_thread_message_loop_
->RunsTasksOnCurrentThread());
69 DCHECK(!file_
.IsValid());
70 // It's the responsibility of the API wrapper around SerialIoHandler to
71 // validate the supplied path against the set of valid port names, and
72 // it is a reasonable assumption that serial port names are ASCII.
73 DCHECK(base::IsStringASCII(port
));
74 base::FilePath
path(base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port
)));
75 int flags
= base::File::FLAG_OPEN
| base::File::FLAG_READ
|
76 base::File::FLAG_EXCLUSIVE_READ
| base::File::FLAG_WRITE
|
77 base::File::FLAG_EXCLUSIVE_WRITE
| base::File::FLAG_ASYNC
|
78 base::File::FLAG_TERMINAL_DEVICE
;
79 base::File
file(path
, flags
);
80 io_message_loop
->PostTask(
82 base::Bind(&SerialIoHandler::FinishOpen
, this, Passed(file
.Pass())));
85 void SerialIoHandler::FinishOpen(base::File file
) {
86 DCHECK(CalledOnValidThread());
87 DCHECK(!open_complete_
.is_null());
88 OpenCompleteCallback callback
= open_complete_
;
89 open_complete_
.Reset();
91 if (!file
.IsValid()) {
98 bool success
= PostOpen();
101 callback
.Run(success
);
104 bool SerialIoHandler::PostOpen() {
108 void SerialIoHandler::Close() {
109 if (file_
.IsValid()) {
110 DCHECK(file_thread_message_loop_
.get());
111 file_thread_message_loop_
->PostTask(
112 FROM_HERE
, base::Bind(&SerialIoHandler::DoClose
, Passed(file_
.Pass())));
117 void SerialIoHandler::DoClose(base::File port
) {
118 // port closed by destructor.
121 void SerialIoHandler::Read(scoped_ptr
<WritableBuffer
> buffer
) {
122 DCHECK(CalledOnValidThread());
123 DCHECK(!IsReadPending());
124 pending_read_buffer_
= buffer
.Pass();
125 read_canceled_
= false;
130 void SerialIoHandler::Write(scoped_ptr
<ReadOnlyBuffer
> buffer
) {
131 DCHECK(CalledOnValidThread());
132 DCHECK(!IsWritePending());
133 pending_write_buffer_
= buffer
.Pass();
134 write_canceled_
= false;
139 void SerialIoHandler::ReadCompleted(int bytes_read
,
140 serial::ReceiveError error
) {
141 DCHECK(CalledOnValidThread());
142 DCHECK(IsReadPending());
143 scoped_ptr
<WritableBuffer
> pending_read_buffer
= pending_read_buffer_
.Pass();
144 if (error
== serial::RECEIVE_ERROR_NONE
) {
145 pending_read_buffer
->Done(bytes_read
);
147 pending_read_buffer
->DoneWithError(bytes_read
, error
);
152 void SerialIoHandler::WriteCompleted(int bytes_written
,
153 serial::SendError error
) {
154 DCHECK(CalledOnValidThread());
155 DCHECK(IsWritePending());
156 scoped_ptr
<ReadOnlyBuffer
> pending_write_buffer
=
157 pending_write_buffer_
.Pass();
158 if (error
== serial::SEND_ERROR_NONE
) {
159 pending_write_buffer
->Done(bytes_written
);
161 pending_write_buffer
->DoneWithError(bytes_written
, error
);
166 bool SerialIoHandler::IsReadPending() const {
167 DCHECK(CalledOnValidThread());
168 return pending_read_buffer_
!= NULL
;
171 bool SerialIoHandler::IsWritePending() const {
172 DCHECK(CalledOnValidThread());
173 return pending_write_buffer_
!= NULL
;
176 void SerialIoHandler::CancelRead(serial::ReceiveError reason
) {
177 DCHECK(CalledOnValidThread());
178 if (IsReadPending() && !read_canceled_
) {
179 read_canceled_
= true;
180 read_cancel_reason_
= reason
;
185 void SerialIoHandler::CancelWrite(serial::SendError reason
) {
186 DCHECK(CalledOnValidThread());
187 if (IsWritePending() && !write_canceled_
) {
188 write_canceled_
= true;
189 write_cancel_reason_
= reason
;
194 void SerialIoHandler::QueueReadCompleted(int bytes_read
,
195 serial::ReceiveError error
) {
196 base::MessageLoop::current()->PostTask(
198 base::Bind(&SerialIoHandler::ReadCompleted
, this, bytes_read
, error
));
201 void SerialIoHandler::QueueWriteCompleted(int bytes_written
,
202 serial::SendError error
) {
203 base::MessageLoop::current()->PostTask(
205 base::Bind(&SerialIoHandler::WriteCompleted
, this, bytes_written
, error
));
208 } // namespace device