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 #ifndef DEVICE_SERIAL_SERIAL_IO_HANDLER_H_ 6 #define DEVICE_SERIAL_SERIAL_IO_HANDLER_H_ 7 8 #include "base/callback.h" 9 #include "base/files/file.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/message_loop/message_loop_proxy.h" 12 #include "base/threading/non_thread_safe.h" 13 #include "device/serial/buffer.h" 14 #include "device/serial/serial.mojom.h" 15 16 namespace device { 17 18 // Provides a simplified interface for performing asynchronous I/O on serial 19 // devices by hiding platform-specific MessageLoop interfaces. Pending I/O 20 // operations hold a reference to this object until completion so that memory 21 // doesn't disappear out from under the OS. 22 class SerialIoHandler : public base::NonThreadSafe, 23 public base::RefCounted<SerialIoHandler> { 24 public: 25 // Constructs an instance of some platform-specific subclass. 26 static scoped_refptr<SerialIoHandler> Create( 27 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop); 28 29 typedef base::Callback<void(bool success)> OpenCompleteCallback; 30 31 // Initiates an asynchronous Open of the device. 32 virtual void Open(const std::string& port, 33 const OpenCompleteCallback& callback); 34 35 // Performs an async Read operation. Behavior is undefined if this is called 36 // while a Read is already pending. Otherwise, the Done or DoneWithError 37 // method on |buffer| will eventually be called with a result. 38 void Read(scoped_ptr<WritableBuffer> buffer); 39 40 // Performs an async Write operation. Behavior is undefined if this is called 41 // while a Write is already pending. Otherwise, the Done or DoneWithError 42 // method on |buffer| will eventually be called with a result. 43 void Write(scoped_ptr<ReadOnlyBuffer> buffer); 44 45 // Indicates whether or not a read is currently pending. 46 bool IsReadPending() const; 47 48 // Indicates whether or not a write is currently pending. 49 bool IsWritePending() const; 50 51 // Attempts to cancel a pending read operation. 52 void CancelRead(serial::ReceiveError reason); 53 54 // Attempts to cancel a pending write operation. 55 void CancelWrite(serial::SendError reason); 56 57 // Flushes input and output buffers. 58 virtual bool Flush() const = 0; 59 60 // Reads current control signals (DCD, CTS, etc.) into an existing 61 // DeviceControlSignals structure. Returns |true| iff the signals were 62 // successfully read. 63 virtual serial::DeviceControlSignalsPtr GetControlSignals() const = 0; 64 65 // Sets one or more control signals (DTR and/or RTS). Returns |true| iff 66 // the signals were successfully set. Unininitialized flags in the 67 // HostControlSignals structure are left unchanged. 68 virtual bool SetControlSignals( 69 const serial::HostControlSignals& control_signals) = 0; 70 71 // Performs platform-specific port configuration. Returns |true| iff 72 // configuration was successful. 73 virtual bool ConfigurePort(const serial::ConnectionOptions& options) = 0; 74 75 // Performs a platform-specific port configuration query. Fills values in an 76 // existing ConnectionInfo. Returns |true| iff port configuration was 77 // successfully retrieved. 78 virtual serial::ConnectionInfoPtr GetPortInfo() const = 0; 79 80 protected: 81 explicit SerialIoHandler( 82 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop); 83 virtual ~SerialIoHandler(); 84 85 // Performs a platform-specific read operation. This must guarantee that 86 // ReadCompleted is called when the underlying async operation is completed 87 // or the SerialIoHandler instance will leak. 88 // NOTE: Implementations of ReadImpl should never call ReadCompleted directly. 89 // Use QueueReadCompleted instead to avoid reentrancy. 90 virtual void ReadImpl() = 0; 91 92 // Performs a platform-specific write operation. This must guarantee that 93 // WriteCompleted is called when the underlying async operation is completed 94 // or the SerialIoHandler instance will leak. 95 // NOTE: Implementations of Writempl should never call WriteCompleted 96 // directly. Use QueueWriteCompleted instead to avoid reentrancy. 97 virtual void WriteImpl() = 0; 98 99 // Platform-specific read cancelation. 100 virtual void CancelReadImpl() = 0; 101 102 // Platform-specific write cancelation. 103 virtual void CancelWriteImpl() = 0; 104 105 // Performs platform-specific, one-time port configuration on open. 106 virtual bool PostOpen(); 107 108 // Called by the implementation to signal that the active read has completed. 109 // WARNING: Calling this method can destroy the SerialIoHandler instance 110 // if the associated I/O operation was the only thing keeping it alive. 111 void ReadCompleted(int bytes_read, serial::ReceiveError error); 112 113 // Called by the implementation to signal that the active write has completed. 114 // WARNING: Calling this method may destroy the SerialIoHandler instance 115 // if the associated I/O operation was the only thing keeping it alive. 116 void WriteCompleted(int bytes_written, serial::SendError error); 117 118 // Queues a ReadCompleted call on the current thread. This is used to allow 119 // ReadImpl to immediately signal completion with 0 bytes and an error, 120 // without being reentrant. 121 void QueueReadCompleted(int bytes_read, serial::ReceiveError error); 122 123 // Queues a WriteCompleted call on the current thread. This is used to allow 124 // WriteImpl to immediately signal completion with 0 bytes and an error, 125 // without being reentrant. 126 void QueueWriteCompleted(int bytes_written, serial::SendError error); 127 128 const base::File& file() const { return file_; } 129 130 char* pending_read_buffer() const { 131 return pending_read_buffer_ ? pending_read_buffer_->GetData() : NULL; 132 } 133 134 uint32_t pending_read_buffer_len() const { 135 return pending_read_buffer_ ? pending_read_buffer_->GetSize() : 0; 136 } 137 138 serial::ReceiveError read_cancel_reason() const { 139 return read_cancel_reason_; 140 } 141 142 bool read_canceled() const { return read_canceled_; } 143 144 const char* pending_write_buffer() const { 145 return pending_write_buffer_ ? pending_write_buffer_->GetData() : NULL; 146 } 147 148 uint32_t pending_write_buffer_len() const { 149 return pending_write_buffer_ ? pending_write_buffer_->GetSize() : 0; 150 } 151 152 serial::SendError write_cancel_reason() const { return write_cancel_reason_; } 153 154 bool write_canceled() const { return write_canceled_; } 155 156 // Possibly fixes up a serial port path name in a platform-specific manner. 157 static std::string MaybeFixUpPortName(const std::string& port_name); 158 159 private: 160 friend class base::RefCounted<SerialIoHandler>; 161 162 // Continues an Open operation on the FILE thread. 163 void StartOpen(const std::string& port, 164 scoped_refptr<base::MessageLoopProxy> io_message_loop); 165 166 // Finalizes an Open operation (continued from StartOpen) on the IO thread. 167 void FinishOpen(base::File file); 168 169 void Close(); 170 171 // Continues a Close operation on the FILE thread. 172 static void DoClose(base::File port); 173 174 // File for the opened serial device. This value is only modified from the IO 175 // thread. 176 base::File file_; 177 178 scoped_ptr<WritableBuffer> pending_read_buffer_; 179 serial::ReceiveError read_cancel_reason_; 180 bool read_canceled_; 181 182 scoped_ptr<ReadOnlyBuffer> pending_write_buffer_; 183 serial::SendError write_cancel_reason_; 184 bool write_canceled_; 185 186 // Callback to handle the completion of a pending Open() request. 187 OpenCompleteCallback open_complete_; 188 189 scoped_refptr<base::MessageLoopProxy> file_thread_message_loop_; 190 191 DISALLOW_COPY_AND_ASSIGN(SerialIoHandler); 192 }; 193 194 } // namespace device 195 196 #endif // DEVICE_SERIAL_SERIAL_IO_HANDLER_H_ 197