Upload upstream chromium 114.0.5735.31
[platform/framework/web/chromium-efl.git] / services / device / serial / serial_io_handler.h
1 // Copyright 2014 The Chromium Authors
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 SERVICES_DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
6 #define SERVICES_DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
7
8 #include <stdint.h>
9
10 #include <memory>
11 #include <string>
12
13 #include "base/files/file.h"
14 #include "base/functional/callback.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/sequence_checker.h"
17 #include "base/task/single_thread_task_runner.h"
18 #include "build/build_config.h"
19 #include "services/device/public/mojom/serial.mojom.h"
20
21 namespace device {
22
23 // Provides a simplified interface for performing asynchronous I/O on serial
24 // devices by hiding platform-specific MessageLoop interfaces. Pending I/O
25 // operations hold a reference to this object until completion so that memory
26 // doesn't disappear out from under the OS.
27 class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
28  public:
29   // Constructs an instance of some platform-specific subclass.
30   static scoped_refptr<SerialIoHandler> Create(
31       const base::FilePath& port,
32       scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
33
34   SerialIoHandler(const SerialIoHandler&) = delete;
35   SerialIoHandler& operator=(const SerialIoHandler&) = delete;
36
37   using OpenCompleteCallback = base::OnceCallback<void(bool success)>;
38   using ReadCompleteCallback =
39       base::OnceCallback<void(uint32_t bytes_read, mojom::SerialReceiveError)>;
40   using WriteCompleteCallback =
41       base::OnceCallback<void(uint32_t bytes_written, mojom::SerialSendError)>;
42
43   // Initiates an asynchronous Open of the device.
44   virtual void Open(const mojom::SerialConnectionOptions& options,
45                     OpenCompleteCallback callback);
46
47 #if BUILDFLAG(IS_CHROMEOS)
48   // Signals that the port has been opened.
49   void OnPathOpened(
50       scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
51       base::ScopedFD fd);
52
53   // Signals that the permission broker failed to open the port.
54   void OnPathOpenError(
55       scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
56       const std::string& error_name,
57       const std::string& error_message);
58
59   // Reports the open error from the permission broker.
60   void ReportPathOpenError(const std::string& error_name,
61                            const std::string& error_message);
62 #endif  // BUILDFLAG(IS_CHROMEOS)
63
64   // Performs an async read operation. Behavior is undefined if this is called
65   // while a read is already pending. Otherwise, |callback| will be called
66   // (potentially synchronously) with a result. |buffer| must remain valid until
67   // |callback| is run.
68   void Read(base::span<uint8_t> buffer, ReadCompleteCallback callback);
69
70   // Performs an async write operation. Behavior is undefined if this is called
71   // while a write is already pending. Otherwise, |callback| will be called
72   // (potentially synchronously) with a result. |buffer| must remain valid until
73   // |callback| is run.
74   void Write(base::span<const uint8_t> buffer, WriteCompleteCallback callback);
75
76   // Indicates whether or not a read is currently pending.
77   bool IsReadPending() const;
78
79   // Indicates whether or not a write is currently pending.
80   bool IsWritePending() const;
81
82   // Attempts to cancel a pending read operation.
83   void CancelRead(mojom::SerialReceiveError reason);
84
85   // Attempts to cancel a pending write operation.
86   void CancelWrite(mojom::SerialSendError reason);
87
88   // Flushes input and output buffers.
89   virtual void Flush(mojom::SerialPortFlushMode mode) const = 0;
90
91   // Drains output buffers.
92   virtual void Drain() = 0;
93
94   // Reads current control signals (DCD, CTS, etc.) into an existing
95   // DeviceControlSignals structure. Returns |true| iff the signals were
96   // successfully read.
97   virtual mojom::SerialPortControlSignalsPtr GetControlSignals() const = 0;
98
99   // Sets one or more control signals. Returns |true| iff the signals were
100   // successfully set. Flags not present in |control_signals| are unchanged.
101   virtual bool SetControlSignals(
102       const mojom::SerialHostControlSignals& control_signals) = 0;
103
104   // Performs platform-specific port configuration. Returns |true| iff
105   // configuration was successful.
106   bool ConfigurePort(const mojom::SerialConnectionOptions& options);
107
108   // Performs a platform-specific port configuration query. Fills values in an
109   // existing ConnectionInfo. Returns |true| iff port configuration was
110   // successfully retrieved.
111   virtual mojom::SerialConnectionInfoPtr GetPortInfo() const = 0;
112
113   // Initiates an asynchronous close of the port.
114   void Close(base::OnceClosure callback);
115
116  protected:
117   explicit SerialIoHandler(
118       const base::FilePath& port,
119       scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
120   virtual ~SerialIoHandler();
121
122   // Performs a platform-specific read operation. This must guarantee that
123   // ReadCompleted is called when the underlying async operation is completed
124   // or the SerialIoHandler instance will leak.
125   // NOTE: Implementations of ReadImpl may call ReadCompleted directly.
126   virtual void ReadImpl() = 0;
127
128   // Performs a platform-specific write operation. This must guarantee that
129   // WriteCompleted is called when the underlying async operation is completed
130   // or the SerialIoHandler instance will leak.
131   // NOTE: Implementations of WriteImpl may call WriteCompleted directly.
132   virtual void WriteImpl() = 0;
133
134   // Platform-specific read cancelation.
135   virtual void CancelReadImpl() = 0;
136
137   // Platform-specific write cancelation.
138   virtual void CancelWriteImpl() = 0;
139
140   // Platform-specific port configuration applies options_ to the device.
141   virtual bool ConfigurePortImpl() = 0;
142
143   // Performs platform-specific, one-time port configuration on open.
144   virtual bool PostOpen();
145
146   // Performs platform-specific operations before |file_| is closed.
147   virtual void PreClose();
148
149   // Called by the implementation to signal that the active read has completed.
150   // WARNING: Calling this method can destroy the SerialIoHandler instance
151   // if the associated I/O operation was the only thing keeping it alive.
152   void ReadCompleted(int bytes_read, mojom::SerialReceiveError error);
153
154   // Called by the implementation to signal that the active write has completed.
155   // WARNING: Calling this method may destroy the SerialIoHandler instance
156   // if the associated I/O operation was the only thing keeping it alive.
157   void WriteCompleted(int bytes_written, mojom::SerialSendError error);
158
159   const base::File& file() const { return file_; }
160
161   base::span<uint8_t> pending_read_buffer() const {
162     return pending_read_buffer_;
163   }
164
165   mojom::SerialReceiveError read_cancel_reason() const {
166     return read_cancel_reason_;
167   }
168
169   bool read_canceled() const { return read_canceled_; }
170
171   base::span<const uint8_t> pending_write_buffer() const {
172     return pending_write_buffer_;
173   }
174
175   mojom::SerialSendError write_cancel_reason() const {
176     return write_cancel_reason_;
177   }
178
179   bool write_canceled() const { return write_canceled_; }
180
181   const mojom::SerialConnectionOptions& options() const { return options_; }
182
183   base::SingleThreadTaskRunner* ui_thread_task_runner() const {
184     return ui_thread_task_runner_.get();
185   }
186
187   const base::FilePath& port() const { return port_; }
188
189   SEQUENCE_CHECKER(sequence_checker_);
190
191  private:
192   friend class base::RefCountedThreadSafe<SerialIoHandler>;
193
194   void MergeConnectionOptions(const mojom::SerialConnectionOptions& options);
195
196   // Continues an Open operation on the FILE thread.
197   void StartOpen(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
198
199   // Finalizes an Open operation (continued from StartOpen) on the IO thread.
200   void FinishOpen(base::File file);
201
202   // Continues a Close operation on the FILE thread.
203   static void DoClose(base::File port);
204
205   // File for the opened serial device. This value is only modified from the IO
206   // thread.
207   base::File file_;
208
209   // Currently applied connection options.
210   mojom::SerialConnectionOptions options_;
211
212   base::span<uint8_t> pending_read_buffer_;
213   ReadCompleteCallback pending_read_callback_;
214   mojom::SerialReceiveError read_cancel_reason_;
215   bool read_canceled_;
216
217   base::span<const uint8_t> pending_write_buffer_;
218   WriteCompleteCallback pending_write_callback_;
219   mojom::SerialSendError write_cancel_reason_;
220   bool write_canceled_;
221
222   // Callback to handle the completion of a pending Open() request.
223   OpenCompleteCallback open_complete_;
224
225   const base::FilePath port_;
226
227   // On Chrome OS, PermissionBrokerClient should be called on the UI thread.
228   scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
229 };
230
231 }  // namespace device
232
233 #endif  // SERVICES_DEVICE_SERIAL_SERIAL_IO_HANDLER_H_