1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifndef DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback.h"
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/files/file.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/ref_counted.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/message_loop/message_loop_proxy.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/threading/non_thread_safe.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "device/serial/buffer.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "device/serial/serial.mojom.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace device {
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Provides a simplified interface for performing asynchronous I/O on serial
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// devices by hiding platform-specific MessageLoop interfaces. Pending I/O
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// operations hold a reference to this object until completion so that memory
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// doesn't disappear out from under the OS.
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SerialIoHandler : public base::NonThreadSafe,
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                        public base::RefCounted<SerialIoHandler> {
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Constructs an instance of some platform-specific subclass.
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  static scoped_refptr<SerialIoHandler> Create(
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_refptr<base::MessageLoopProxy> file_thread_message_loop);
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typedef base::Callback<void(bool success)> OpenCompleteCallback;
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Initiates an asynchronous Open of the device.
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual void Open(const std::string& port,
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                    const OpenCompleteCallback& callback);
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Performs an async Read operation. Behavior is undefined if this is called
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // while a Read is already pending. Otherwise, the Done or DoneWithError
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // method on |buffer| will eventually be called with a result.
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void Read(scoped_ptr<WritableBuffer> buffer);
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Performs an async Write operation. Behavior is undefined if this is called
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // while a Write is already pending. Otherwise, the Done or DoneWithError
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // method on |buffer| will eventually be called with a result.
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  void Write(scoped_ptr<ReadOnlyBuffer> buffer);
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Indicates whether or not a read is currently pending.
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool IsReadPending() const;
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Indicates whether or not a write is currently pending.
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool IsWritePending() const;
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Attempts to cancel a pending read operation.
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void CancelRead(serial::ReceiveError reason);
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Attempts to cancel a pending write operation.
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void CancelWrite(serial::SendError reason);
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Flushes input and output buffers.
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual bool Flush() const = 0;
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Reads current control signals (DCD, CTS, etc.) into an existing
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // DeviceControlSignals structure. Returns |true| iff the signals were
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // successfully read.
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual serial::DeviceControlSignalsPtr GetControlSignals() const = 0;
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Sets one or more control signals (DTR and/or RTS). Returns |true| iff
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // the signals were successfully set. Unininitialized flags in the
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // HostControlSignals structure are left unchanged.
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual bool SetControlSignals(
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const serial::HostControlSignals& control_signals) = 0;
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Performs platform-specific port configuration. Returns |true| iff
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // configuration was successful.
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual bool ConfigurePort(const serial::ConnectionOptions& options) = 0;
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Performs a platform-specific port configuration query. Fills values in an
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // existing ConnectionInfo. Returns |true| iff port configuration was
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // successfully retrieved.
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual serial::ConnectionInfoPtr GetPortInfo() const = 0;
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) protected:
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  explicit SerialIoHandler(
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      scoped_refptr<base::MessageLoopProxy> file_thread_message_loop);
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual ~SerialIoHandler();
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Performs a platform-specific read operation. This must guarantee that
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // ReadCompleted is called when the underlying async operation is completed
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // or the SerialIoHandler instance will leak.
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NOTE: Implementations of ReadImpl should never call ReadCompleted directly.
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Use QueueReadCompleted instead to avoid reentrancy.
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void ReadImpl() = 0;
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Performs a platform-specific write operation. This must guarantee that
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // WriteCompleted is called when the underlying async operation is completed
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // or the SerialIoHandler instance will leak.
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // NOTE: Implementations of Writempl should never call WriteCompleted
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // directly. Use QueueWriteCompleted instead to avoid reentrancy.
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void WriteImpl() = 0;
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Platform-specific read cancelation.
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void CancelReadImpl() = 0;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Platform-specific write cancelation.
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  virtual void CancelWriteImpl() = 0;
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Performs platform-specific, one-time port configuration on open.
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  virtual bool PostOpen();
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by the implementation to signal that the active read has completed.
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // WARNING: Calling this method can destroy the SerialIoHandler instance
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // if the associated I/O operation was the only thing keeping it alive.
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void ReadCompleted(int bytes_read, serial::ReceiveError error);
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Called by the implementation to signal that the active write has completed.
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // WARNING: Calling this method may destroy the SerialIoHandler instance
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // if the associated I/O operation was the only thing keeping it alive.
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void WriteCompleted(int bytes_written, serial::SendError error);
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Queues a ReadCompleted call on the current thread. This is used to allow
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // ReadImpl to immediately signal completion with 0 bytes and an error,
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // without being reentrant.
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void QueueReadCompleted(int bytes_read, serial::ReceiveError error);
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Queues a WriteCompleted call on the current thread. This is used to allow
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // WriteImpl to immediately signal completion with 0 bytes and an error,
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // without being reentrant.
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void QueueWriteCompleted(int bytes_written, serial::SendError error);
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const base::File& file() const { return file_; }
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  char* pending_read_buffer() const {
1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return pending_read_buffer_ ? pending_read_buffer_->GetData() : NULL;
132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t pending_read_buffer_len() const {
1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return pending_read_buffer_ ? pending_read_buffer_->GetSize() : 0;
1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  serial::ReceiveError read_cancel_reason() const {
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return read_cancel_reason_;
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool read_canceled() const { return read_canceled_; }
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const char* pending_write_buffer() const {
1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return pending_write_buffer_ ? pending_write_buffer_->GetData() : NULL;
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  uint32_t pending_write_buffer_len() const {
1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return pending_write_buffer_ ? pending_write_buffer_->GetSize() : 0;
1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  serial::SendError write_cancel_reason() const { return write_cancel_reason_; }
153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  bool write_canceled() const { return write_canceled_; }
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Possibly fixes up a serial port path name in a platform-specific manner.
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  static std::string MaybeFixUpPortName(const std::string& port_name);
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  friend class base::RefCounted<SerialIoHandler>;
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Continues an Open operation on the FILE thread.
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void StartOpen(const std::string& port,
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 scoped_refptr<base::MessageLoopProxy> io_message_loop);
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Finalizes an Open operation (continued from StartOpen) on the IO thread.
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void FinishOpen(base::File file);
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void Close();
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Continues a Close operation on the FILE thread.
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  static void DoClose(base::File port);
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // File for the opened serial device. This value is only modified from the IO
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // thread.
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::File file_;
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<WritableBuffer> pending_read_buffer_;
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  serial::ReceiveError read_cancel_reason_;
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool read_canceled_;
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<ReadOnlyBuffer> pending_write_buffer_;
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  serial::SendError write_cancel_reason_;
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool write_canceled_;
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Callback to handle the completion of a pending Open() request.
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  OpenCompleteCallback open_complete_;
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_refptr<base::MessageLoopProxy> file_thread_message_loop_;
190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SerialIoHandler);
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace device
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif  // DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
197