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 : file_thread_message_loop_(file_thread_message_loop) {
19 SerialIoHandler::~SerialIoHandler() {
20 DCHECK(CalledOnValidThread());
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(
32 base::Bind(&SerialIoHandler::StartOpen,
35 base::MessageLoopProxy::current()));
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(
56 base::Bind(&SerialIoHandler::FinishOpen, this, Passed(file.Pass())));
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();
65 if (!file.IsValid()) {
72 bool success = PostOpen();
75 callback.Run(success);
78 bool SerialIoHandler::PostOpen() {
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())));
91 void SerialIoHandler::DoClose(base::File port) {
92 // port closed by destructor.
95 void SerialIoHandler::Read(scoped_ptr<WritableBuffer> buffer) {
96 DCHECK(CalledOnValidThread());
97 DCHECK(!IsReadPending());
98 pending_read_buffer_ = buffer.Pass();
99 read_canceled_ = false;
104 void SerialIoHandler::Write(scoped_ptr<ReadOnlyBuffer> buffer) {
105 DCHECK(CalledOnValidThread());
106 DCHECK(!IsWritePending());
107 pending_write_buffer_ = buffer.Pass();
108 write_canceled_ = false;
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);
120 pending_read_buffer_->DoneWithError(bytes_read, error);
122 pending_read_buffer_.reset();
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);
133 pending_write_buffer_->DoneWithError(bytes_written, error);
135 pending_write_buffer_.reset();
139 bool SerialIoHandler::IsReadPending() const {
140 DCHECK(CalledOnValidThread());
141 return pending_read_buffer_ != NULL;
144 bool SerialIoHandler::IsWritePending() const {
145 DCHECK(CalledOnValidThread());
146 return pending_write_buffer_ != NULL;
149 void SerialIoHandler::CancelRead(serial::ReceiveError reason) {
150 DCHECK(CalledOnValidThread());
151 if (IsReadPending() && !read_canceled_) {
152 read_canceled_ = true;
153 read_cancel_reason_ = reason;
158 void SerialIoHandler::CancelWrite(serial::SendError reason) {
159 DCHECK(CalledOnValidThread());
160 if (IsWritePending() && !write_canceled_) {
161 write_canceled_ = true;
162 write_cancel_reason_ = reason;
167 void SerialIoHandler::QueueReadCompleted(int bytes_read,
168 serial::ReceiveError error) {
169 base::MessageLoop::current()->PostTask(
171 base::Bind(&SerialIoHandler::ReadCompleted, this, bytes_read, error));
174 void SerialIoHandler::QueueWriteCompleted(int bytes_written,
175 serial::SendError error) {
176 base::MessageLoop::current()->PostTask(
178 base::Bind(&SerialIoHandler::WriteCompleted, this, bytes_written, error));
181 } // namespace device