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