Home | History | Annotate | Download | only in serial
      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