1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "device/serial/serial_io_handler.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/bind.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/file_path.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/message_loop/message_loop.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_util.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace device { 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SerialIoHandler::SerialIoHandler( 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<base::MessageLoopProxy> file_thread_message_loop) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : file_thread_message_loop_(file_thread_message_loop) { 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 19116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSerialIoHandler::~SerialIoHandler() { 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Close(); 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::Open(const std::string& port, 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const OpenCompleteCallback& callback) { 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(open_complete_.is_null()); 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch open_complete_ = callback; 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(file_thread_message_loop_.get()); 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file_thread_message_loop_->PostTask( 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&SerialIoHandler::StartOpen, 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this, 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch port, 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoopProxy::current())); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::StartOpen( 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& port, 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<base::MessageLoopProxy> io_message_loop) { 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!open_complete_.is_null()); 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(file_thread_message_loop_->RunsTasksOnCurrentThread()); 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!file_.IsValid()); 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // It's the responsibility of the API wrapper around SerialIoHandler to 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // validate the supplied path against the set of valid port names, and 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // it is a reasonable assumption that serial port names are ASCII. 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(base::IsStringASCII(port)); 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::FilePath path(base::FilePath::FromUTF8Unsafe(MaybeFixUpPortName(port))); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int flags = base::File::FLAG_OPEN | base::File::FLAG_READ | 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_WRITE | 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC | 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File::FLAG_TERMINAL_DEVICE; 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::File file(path, flags); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch io_message_loop->PostTask( 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&SerialIoHandler::FinishOpen, this, Passed(file.Pass()))); 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::FinishOpen(base::File file) { 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!open_complete_.is_null()); 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch OpenCompleteCallback callback = open_complete_; 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch open_complete_.Reset(); 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!file.IsValid()) { 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(false); 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file_ = file.Pass(); 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool success = PostOpen(); 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!success) 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Close(); 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback.Run(success); 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandler::PostOpen() { 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::Close() { 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (file_.IsValid()) { 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(file_thread_message_loop_.get()); 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch file_thread_message_loop_->PostTask( 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, base::Bind(&SerialIoHandler::DoClose, Passed(file_.Pass()))); 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::DoClose(base::File port) { 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // port closed by destructor. 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialIoHandler::Read(scoped_ptr<WritableBuffer> buffer) { 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!IsReadPending()); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_read_buffer_ = buffer.Pass(); 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_canceled_ = false; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddRef(); 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ReadImpl(); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void SerialIoHandler::Write(scoped_ptr<ReadOnlyBuffer> buffer) { 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!IsWritePending()); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_write_buffer_ = buffer.Pass(); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_canceled_ = false; 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddRef(); 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WriteImpl(); 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::ReadCompleted(int bytes_read, 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::ReceiveError error) { 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(IsReadPending()); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<WritableBuffer> pending_read_buffer = pending_read_buffer_.Pass(); 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error == serial::RECEIVE_ERROR_NONE) { 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_buffer->Done(bytes_read); 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_read_buffer->DoneWithError(bytes_read, error); 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Release(); 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::WriteCompleted(int bytes_written, 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::SendError error) { 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(IsWritePending()); 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ReadOnlyBuffer> pending_write_buffer = 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_write_buffer_.Pass(); 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (error == serial::SEND_ERROR_NONE) { 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_write_buffer->Done(bytes_written); 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else { 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_write_buffer->DoneWithError(bytes_written, error); 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Release(); 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandler::IsReadPending() const { 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return pending_read_buffer_ != NULL; 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool SerialIoHandler::IsWritePending() const { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return pending_write_buffer_ != NULL; 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::CancelRead(serial::ReceiveError reason) { 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (IsReadPending() && !read_canceled_) { 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_canceled_ = true; 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch read_cancel_reason_ = reason; 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelReadImpl(); 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::CancelWrite(serial::SendError reason) { 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(CalledOnValidThread()); 1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (IsWritePending() && !write_canceled_) { 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_canceled_ = true; 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch write_cancel_reason_ = reason; 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CancelWriteImpl(); 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::QueueReadCompleted(int bytes_read, 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::ReceiveError error) { 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoop::current()->PostTask( 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&SerialIoHandler::ReadCompleted, this, bytes_read, error)); 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SerialIoHandler::QueueWriteCompleted(int bytes_written, 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch serial::SendError error) { 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::MessageLoop::current()->PostTask( 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch FROM_HERE, 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Bind(&SerialIoHandler::WriteCompleted, this, bytes_written, error)); 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace device 183