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 EXTENSIONS_BROWSER_API_SERIAL_SERIAL_CONNECTION_H_ 6 #define EXTENSIONS_BROWSER_API_SERIAL_SERIAL_CONNECTION_H_ 7 8 #include <string> 9 10 #include "base/callback.h" 11 #include "base/memory/weak_ptr.h" 12 #include "base/time/time.h" 13 #include "content/public/browser/browser_thread.h" 14 #include "device/serial/serial_io_handler.h" 15 #include "extensions/browser/api/api_resource.h" 16 #include "extensions/browser/api/api_resource_manager.h" 17 #include "extensions/common/api/serial.h" 18 #include "net/base/io_buffer.h" 19 20 using content::BrowserThread; 21 22 namespace extensions { 23 24 // Encapsulates an open serial port. 25 // NOTE: Instances of this object should only be constructed on the IO thread, 26 // and all methods should only be called on the IO thread unless otherwise 27 // noted. 28 class SerialConnection : public ApiResource, 29 public base::SupportsWeakPtr<SerialConnection> { 30 public: 31 typedef device::SerialIoHandler::OpenCompleteCallback OpenCompleteCallback; 32 33 // This is the callback type expected by Receive. Note that an error result 34 // does not necessarily imply an empty |data| string, since a receive may 35 // complete partially before being interrupted by an error condition. 36 typedef base::Callback< 37 void(const std::string& data, core_api::serial::ReceiveError error)> 38 ReceiveCompleteCallback; 39 40 // This is the callback type expected by Send. Note that an error result 41 // does not necessarily imply 0 bytes sent, since a send may complete 42 // partially before being interrupted by an error condition. 43 typedef base::Callback< 44 void(int bytes_sent, core_api::serial::SendError error)> 45 SendCompleteCallback; 46 47 SerialConnection(const std::string& port, 48 const std::string& owner_extension_id); 49 virtual ~SerialConnection(); 50 51 // ApiResource override. 52 virtual bool IsPersistent() const OVERRIDE; 53 54 void set_persistent(bool persistent) { persistent_ = persistent; } 55 bool persistent() const { return persistent_; } 56 57 void set_name(const std::string& name) { name_ = name; } 58 const std::string& name() const { return name_; } 59 60 void set_buffer_size(int buffer_size); 61 int buffer_size() const { return buffer_size_; } 62 63 void set_receive_timeout(int receive_timeout); 64 int receive_timeout() const { return receive_timeout_; } 65 66 void set_send_timeout(int send_timeout); 67 int send_timeout() const { return send_timeout_; } 68 69 void set_paused(bool paused); 70 bool paused() const { return paused_; } 71 72 // Initiates an asynchronous Open of the device. It is the caller's 73 // responsibility to ensure that this SerialConnection stays alive 74 // until |callback| is run. 75 void Open(const OpenCompleteCallback& callback); 76 77 // Begins an asynchronous receive operation. Calling this while a Receive 78 // is already pending is a no-op and returns |false| without calling 79 // |callback|. 80 bool Receive(const ReceiveCompleteCallback& callback); 81 82 // Begins an asynchronous send operation. Calling this while a Send 83 // is already pending is a no-op and returns |false| without calling 84 // |callback|. 85 bool Send(const std::string& data, const SendCompleteCallback& callback); 86 87 // Flushes input and output buffers. 88 bool Flush() const; 89 90 // Configures some subset of port options for this connection. 91 // Omitted options are unchanged. Returns |true| iff the configuration 92 // changes were successful. 93 bool Configure(const core_api::serial::ConnectionOptions& options); 94 95 // Connection configuration query. Fills values in an existing 96 // ConnectionInfo. Returns |true| iff the connection's information 97 // was successfully retrieved. 98 bool GetInfo(core_api::serial::ConnectionInfo* info) const; 99 100 // Reads current control signals (DCD, CTS, etc.) into an existing 101 // DeviceControlSignals structure. Returns |true| iff the signals were 102 // successfully read. 103 bool GetControlSignals( 104 core_api::serial::DeviceControlSignals* control_signals) const; 105 106 // Sets one or more control signals (DTR and/or RTS). Returns |true| iff 107 // the signals were successfully set. Unininitialized flags in the 108 // HostControlSignals structure are left unchanged. 109 bool SetControlSignals( 110 const core_api::serial::HostControlSignals& control_signals); 111 112 // Overrides |io_handler_| for testing. 113 void SetIoHandlerForTest(scoped_refptr<device::SerialIoHandler> handler); 114 115 static const BrowserThread::ID kThreadId = BrowserThread::IO; 116 117 private: 118 friend class ApiResourceManager<SerialConnection>; 119 static const char* service_name() { return "SerialConnectionManager"; } 120 121 // Encapsulates a cancelable, delayed timeout task. Posts a delayed 122 // task upon construction and implicitly cancels the task upon 123 // destruction if it hasn't run yet. 124 class TimeoutTask { 125 public: 126 TimeoutTask(const base::Closure& closure, const base::TimeDelta& delay); 127 ~TimeoutTask(); 128 129 private: 130 void Run() const; 131 132 base::WeakPtrFactory<TimeoutTask> weak_factory_; 133 base::Closure closure_; 134 base::TimeDelta delay_; 135 }; 136 137 // Handles a receive timeout. 138 void OnReceiveTimeout(); 139 140 // Handles a send timeout. 141 void OnSendTimeout(); 142 143 // Receives read completion notification from the |io_handler_|. 144 void OnAsyncReadComplete(int bytes_read, device::serial::ReceiveError error); 145 146 // Receives write completion notification from the |io_handler_|. 147 void OnAsyncWriteComplete(int bytes_sent, device::serial::SendError error); 148 149 // The pathname of the serial device. 150 std::string port_; 151 152 // Flag indicating whether or not the connection should persist when 153 // its host app is suspended. 154 bool persistent_; 155 156 // User-specified connection name. 157 std::string name_; 158 159 // Size of the receive buffer. 160 int buffer_size_; 161 162 // Amount of time (in ms) to wait for a Read to succeed before triggering a 163 // timeout response via onReceiveError. 164 int receive_timeout_; 165 166 // Amount of time (in ms) to wait for a Write to succeed before triggering 167 // a timeout response. 168 int send_timeout_; 169 170 // Flag indicating that the connection is paused. A paused connection will not 171 // raise new onReceive events. 172 bool paused_; 173 174 // Callback to handle the completion of a pending Receive() request. 175 ReceiveCompleteCallback receive_complete_; 176 177 // Callback to handle the completion of a pending Send() request. 178 SendCompleteCallback send_complete_; 179 180 // Closure which will trigger a receive timeout unless cancelled. Reset on 181 // initialization and after every successful Receive(). 182 scoped_ptr<TimeoutTask> receive_timeout_task_; 183 184 // Write timeout closure. Reset on initialization and after every successful 185 // Send(). 186 scoped_ptr<TimeoutTask> send_timeout_task_; 187 188 scoped_refptr<net::IOBuffer> receive_buffer_; 189 190 // Asynchronous I/O handler. 191 scoped_refptr<device::SerialIoHandler> io_handler_; 192 }; 193 194 } // namespace extensions 195 196 namespace mojo { 197 198 template <> 199 struct TypeConverter<device::serial::HostControlSignalsPtr, 200 extensions::core_api::serial::HostControlSignals> { 201 static device::serial::HostControlSignalsPtr Convert( 202 const extensions::core_api::serial::HostControlSignals& input); 203 }; 204 205 template <> 206 struct TypeConverter<device::serial::ConnectionOptionsPtr, 207 extensions::core_api::serial::ConnectionOptions> { 208 static device::serial::ConnectionOptionsPtr Convert( 209 const extensions::core_api::serial::ConnectionOptions& input); 210 }; 211 212 } // namespace mojo 213 214 #endif // EXTENSIONS_BROWSER_API_SERIAL_SERIAL_CONNECTION_H_ 215