Home | History | Annotate | Download | only in serial
      1 // Copyright 2013 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_IO_HANDLER_H_
      6 #define CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_IO_HANDLER_H_
      7 
      8 #include "base/callback.h"
      9 #include "base/memory/ref_counted.h"
     10 #include "base/platform_file.h"
     11 #include "base/threading/non_thread_safe.h"
     12 #include "chrome/common/extensions/api/serial.h"
     13 #include "net/base/io_buffer.h"
     14 
     15 namespace extensions {
     16 
     17 // Provides a simplified interface for performing asynchronous I/O on serial
     18 // devices by hiding platform-specific MessageLoop interfaces. Pending I/O
     19 // operations hold a reference to this object until completion so that memory
     20 // doesn't disappear out from under the OS.
     21 class SerialIoHandler : public base::NonThreadSafe,
     22                         public base::RefCounted<SerialIoHandler> {
     23  public:
     24   // Constructs an instance of some platform-specific subclass.
     25   static scoped_refptr<SerialIoHandler> Create();
     26 
     27   // Called with a string of bytes read, and a result code. Note that an error
     28   // result does not necessarily imply 0 bytes read.
     29   typedef base::Callback<void(const std::string& data,
     30                               api::serial::ReceiveError error)>
     31       ReadCompleteCallback;
     32 
     33   // Called with the number of bytes written and a result code. Note that an
     34   // error result does not necessarily imply 0 bytes written.
     35   typedef base::Callback<void(int bytes_written, api::serial::SendError error)>
     36       WriteCompleteCallback;
     37 
     38   // Initializes the handler on the current message loop. Must be called exactly
     39   // once before performing any I/O through the handler.
     40   void Initialize(base::PlatformFile file,
     41                   const ReadCompleteCallback& read_callback,
     42                   const WriteCompleteCallback& write_callback);
     43 
     44   // Performs an async Read operation. Behavior is undefined if this is called
     45   // while a Read is already pending. Otherwise, the ReadCompleteCallback
     46   // (see above) will eventually be called with a result.
     47   void Read(int max_bytes);
     48 
     49   // Performs an async Write operation. Behavior is undefined if this is called
     50   // while a Write is already pending. Otherwise, the WriteCompleteCallback
     51   // (see above) will eventually be called with a result.
     52   void Write(const std::string& data);
     53 
     54   // Indicates whether or not a read is currently pending.
     55   bool IsReadPending() const;
     56 
     57   // Indicates whether or not a write is currently pending.
     58   bool IsWritePending() const;
     59 
     60   // Attempts to cancel a pending read operation.
     61   void CancelRead(api::serial::ReceiveError reason);
     62 
     63   // Attempts to cancel a pending write operation.
     64   void CancelWrite(api::serial::SendError reason);
     65 
     66  protected:
     67   SerialIoHandler();
     68   virtual ~SerialIoHandler();
     69 
     70   // Performs platform-specific initialization. |file_|, |read_complete_| and
     71   // |write_complete_| all hold initialized values before this is called.
     72   virtual void InitializeImpl() {}
     73 
     74   // Performs a platform-specific read operation. This must guarantee that
     75   // ReadCompleted is called when the underlying async operation is completed
     76   // or the SerialIoHandler instance will leak.
     77   // NOTE: Implementations of ReadImpl should never call ReadCompleted directly.
     78   // Use QueueReadCompleted instead to avoid reentrancy.
     79   virtual void ReadImpl() = 0;
     80 
     81   // Performs a platform-specific write operation. This must guarantee that
     82   // WriteCompleted is called when the underlying async operation is completed
     83   // or the SerialIoHandler instance will leak.
     84   // NOTE: Implementations of Writempl should never call WriteCompleted
     85   // directly. Use QueueWriteCompleted instead to avoid reentrancy.
     86   virtual void WriteImpl() = 0;
     87 
     88   // Platform-specific read cancelation.
     89   virtual void CancelReadImpl() = 0;
     90 
     91   // Platform-specific write cancelation.
     92   virtual void CancelWriteImpl() = 0;
     93 
     94   // Called by the implementation to signal that the active read has completed.
     95   // WARNING: Calling this method can destroy the SerialIoHandler instance
     96   // if the associated I/O operation was the only thing keeping it alive.
     97   void ReadCompleted(int bytes_read, api::serial::ReceiveError error);
     98 
     99   // Called by the implementation to signal that the active write has completed.
    100   // WARNING: Calling this method may destroy the SerialIoHandler instance
    101   // if the associated I/O operation was the only thing keeping it alive.
    102   void WriteCompleted(int bytes_written, api::serial::SendError error);
    103 
    104   // Queues a ReadCompleted call on the current thread. This is used to allow
    105   // ReadImpl to immediately signal completion with 0 bytes and an error,
    106   // without being reentrant.
    107   void QueueReadCompleted(int bytes_read, api::serial::ReceiveError error);
    108 
    109   // Queues a WriteCompleted call on the current thread. This is used to allow
    110   // WriteImpl to immediately signal completion with 0 bytes and an error,
    111   // without being reentrant.
    112   void QueueWriteCompleted(int bytes_written, api::serial::SendError error);
    113 
    114   base::PlatformFile file() const {
    115     return file_;
    116   }
    117 
    118   net::IOBuffer* pending_read_buffer() const {
    119     return pending_read_buffer_.get();
    120   }
    121 
    122   int pending_read_buffer_len() const {
    123     return pending_read_buffer_len_;
    124   }
    125 
    126   api::serial::ReceiveError read_cancel_reason() const {
    127     return read_cancel_reason_;
    128   }
    129 
    130   bool read_canceled() const {
    131     return read_canceled_;
    132   }
    133 
    134   net::IOBuffer* pending_write_buffer() const {
    135     return pending_write_buffer_.get();
    136   }
    137 
    138   int pending_write_buffer_len() const {
    139     return pending_write_buffer_len_;
    140   }
    141 
    142   api::serial::SendError write_cancel_reason() const {
    143     return write_cancel_reason_;
    144   }
    145 
    146   bool write_canceled() const {
    147     return write_canceled_;
    148   }
    149 
    150  private:
    151   friend class base::RefCounted<SerialIoHandler>;
    152 
    153   base::PlatformFile file_;
    154 
    155   scoped_refptr<net::IOBuffer> pending_read_buffer_;
    156   int pending_read_buffer_len_;
    157   api::serial::ReceiveError read_cancel_reason_;
    158   bool read_canceled_;
    159 
    160   scoped_refptr<net::IOBuffer> pending_write_buffer_;
    161   int pending_write_buffer_len_;
    162   api::serial::SendError write_cancel_reason_;
    163   bool write_canceled_;
    164 
    165   ReadCompleteCallback read_complete_;
    166   WriteCompleteCallback write_complete_;
    167 
    168   DISALLOW_COPY_AND_ASSIGN(SerialIoHandler);
    169 };
    170 
    171 }  // namespace extensions
    172 
    173 #endif  // CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_IO_HANDLER_H_
    174