• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
file()128   const base::File& file() const { return file_; }
129 
pending_read_buffer()130   char* pending_read_buffer() const {
131     return pending_read_buffer_ ? pending_read_buffer_->GetData() : NULL;
132   }
133 
pending_read_buffer_len()134   uint32_t pending_read_buffer_len() const {
135     return pending_read_buffer_ ? pending_read_buffer_->GetSize() : 0;
136   }
137 
read_cancel_reason()138   serial::ReceiveError read_cancel_reason() const {
139     return read_cancel_reason_;
140   }
141 
read_canceled()142   bool read_canceled() const { return read_canceled_; }
143 
pending_write_buffer()144   const char* pending_write_buffer() const {
145     return pending_write_buffer_ ? pending_write_buffer_->GetData() : NULL;
146   }
147 
pending_write_buffer_len()148   uint32_t pending_write_buffer_len() const {
149     return pending_write_buffer_ ? pending_write_buffer_->GetSize() : 0;
150   }
151 
write_cancel_reason()152   serial::SendError write_cancel_reason() const { return write_cancel_reason_; }
153 
write_canceled()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