forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
serial_io_handler.h
251 lines (186 loc) · 9.25 KB
/
serial_io_handler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
#define DEVICE_SERIAL_SERIAL_IO_HANDLER_H_
#include <stdint.h>
#include <memory>
#include "base/callback.h"
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "device/serial/buffer.h"
#include "device/serial/serial.mojom.h"
namespace device {
// Provides a simplified interface for performing asynchronous I/O on serial
// devices by hiding platform-specific MessageLoop interfaces. Pending I/O
// operations hold a reference to this object until completion so that memory
// doesn't disappear out from under the OS.
class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
public:
// Constructs an instance of some platform-specific subclass.
static scoped_refptr<SerialIoHandler> Create(
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
typedef base::Callback<void(bool success)> OpenCompleteCallback;
// Initiates an asynchronous Open of the device.
virtual void Open(const std::string& port,
const mojom::SerialConnectionOptions& options,
const OpenCompleteCallback& callback);
#if defined(OS_CHROMEOS)
// Signals that the port has been opened.
void OnPathOpened(
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
base::ScopedFD fd);
// Signals that the permission broker failed to open the port.
void OnPathOpenError(
scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner,
const std::string& error_name,
const std::string& error_message);
// Reports the open error from the permission broker.
void ReportPathOpenError(const std::string& error_name,
const std::string& error_message);
#endif // defined(OS_CHROMEOS)
// Performs an async Read operation. Behavior is undefined if this is called
// while a Read is already pending. Otherwise, the Done or DoneWithError
// method on |buffer| will eventually be called with a result.
void Read(std::unique_ptr<WritableBuffer> buffer);
// Performs an async Write operation. Behavior is undefined if this is called
// while a Write is already pending. Otherwise, the Done or DoneWithError
// method on |buffer| will eventually be called with a result.
void Write(std::unique_ptr<ReadOnlyBuffer> buffer);
// Indicates whether or not a read is currently pending.
bool IsReadPending() const;
// Indicates whether or not a write is currently pending.
bool IsWritePending() const;
// Attempts to cancel a pending read operation.
void CancelRead(mojom::SerialReceiveError reason);
// Attempts to cancel a pending write operation.
void CancelWrite(mojom::SerialSendError reason);
// Flushes input and output buffers.
virtual bool Flush() const = 0;
// Reads current control signals (DCD, CTS, etc.) into an existing
// DeviceControlSignals structure. Returns |true| iff the signals were
// successfully read.
virtual mojom::SerialDeviceControlSignalsPtr GetControlSignals() const = 0;
// Sets one or more control signals (DTR and/or RTS). Returns |true| iff
// the signals were successfully set. Unininitialized flags in the
// HostControlSignals structure are left unchanged.
virtual bool SetControlSignals(
const mojom::SerialHostControlSignals& control_signals) = 0;
// Performs platform-specific port configuration. Returns |true| iff
// configuration was successful.
bool ConfigurePort(const mojom::SerialConnectionOptions& options);
// Performs a platform-specific port configuration query. Fills values in an
// existing ConnectionInfo. Returns |true| iff port configuration was
// successfully retrieved.
virtual mojom::SerialConnectionInfoPtr GetPortInfo() const = 0;
// Initiates a BREAK signal. Places the transmission line in a break state
// until the |ClearBreak| is called.
virtual bool SetBreak() = 0;
// Terminates the BREAK signal. Places the transmission line in a nonbreak
// state.
virtual bool ClearBreak() = 0;
protected:
explicit SerialIoHandler(
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner);
virtual ~SerialIoHandler();
// Performs a platform-specific read operation. This must guarantee that
// ReadCompleted is called when the underlying async operation is completed
// or the SerialIoHandler instance will leak.
// NOTE: Implementations of ReadImpl should never call ReadCompleted directly.
// Use QueueReadCompleted instead to avoid reentrancy.
virtual void ReadImpl() = 0;
// Performs a platform-specific write operation. This must guarantee that
// WriteCompleted is called when the underlying async operation is completed
// or the SerialIoHandler instance will leak.
// NOTE: Implementations of WriteImpl should never call WriteCompleted
// directly. Use QueueWriteCompleted instead to avoid reentrancy.
virtual void WriteImpl() = 0;
// Platform-specific read cancelation.
virtual void CancelReadImpl() = 0;
// Platform-specific write cancelation.
virtual void CancelWriteImpl() = 0;
// Platform-specific port configuration applies options_ to the device.
virtual bool ConfigurePortImpl() = 0;
// Performs platform-specific, one-time port configuration on open.
virtual bool PostOpen();
// Called by the implementation to signal that the active read has completed.
// WARNING: Calling this method can destroy the SerialIoHandler instance
// if the associated I/O operation was the only thing keeping it alive.
void ReadCompleted(int bytes_read, mojom::SerialReceiveError error);
// Called by the implementation to signal that the active write has completed.
// WARNING: Calling this method may destroy the SerialIoHandler instance
// if the associated I/O operation was the only thing keeping it alive.
void WriteCompleted(int bytes_written, mojom::SerialSendError error);
// Queues a ReadCompleted call on the current thread. This is used to allow
// ReadImpl to immediately signal completion with 0 bytes and an error,
// without being reentrant.
void QueueReadCompleted(int bytes_read, mojom::SerialReceiveError error);
// Queues a WriteCompleted call on the current thread. This is used to allow
// WriteImpl to immediately signal completion with 0 bytes and an error,
// without being reentrant.
void QueueWriteCompleted(int bytes_written, mojom::SerialSendError error);
const base::File& file() const { return file_; }
char* pending_read_buffer() const {
return pending_read_buffer_ ? pending_read_buffer_->GetData() : NULL;
}
uint32_t pending_read_buffer_len() const {
return pending_read_buffer_ ? pending_read_buffer_->GetSize() : 0;
}
mojom::SerialReceiveError read_cancel_reason() const {
return read_cancel_reason_;
}
bool read_canceled() const { return read_canceled_; }
const char* pending_write_buffer() const {
return pending_write_buffer_ ? pending_write_buffer_->GetData() : NULL;
}
uint32_t pending_write_buffer_len() const {
return pending_write_buffer_ ? pending_write_buffer_->GetSize() : 0;
}
mojom::SerialSendError write_cancel_reason() const {
return write_cancel_reason_;
}
bool write_canceled() const { return write_canceled_; }
const mojom::SerialConnectionOptions& options() const { return options_; }
// Possibly fixes up a serial port path name in a platform-specific manner.
static std::string MaybeFixUpPortName(const std::string& port_name);
base::SingleThreadTaskRunner* ui_thread_task_runner() const {
return ui_thread_task_runner_.get();
}
const std::string& port() const { return port_; }
SEQUENCE_CHECKER(sequence_checker_);
private:
friend class base::RefCountedThreadSafe<SerialIoHandler>;
void MergeConnectionOptions(const mojom::SerialConnectionOptions& options);
// Continues an Open operation on the FILE thread.
void StartOpen(const std::string& port,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
// Finalizes an Open operation (continued from StartOpen) on the IO thread.
void FinishOpen(base::File file);
void Close();
// Continues a Close operation on the FILE thread.
static void DoClose(base::File port);
// File for the opened serial device. This value is only modified from the IO
// thread.
base::File file_;
// Currently applied connection options.
mojom::SerialConnectionOptions options_;
std::unique_ptr<WritableBuffer> pending_read_buffer_;
mojom::SerialReceiveError read_cancel_reason_;
bool read_canceled_;
std::unique_ptr<ReadOnlyBuffer> pending_write_buffer_;
mojom::SerialSendError write_cancel_reason_;
bool write_canceled_;
// Callback to handle the completion of a pending Open() request.
OpenCompleteCallback open_complete_;
// On Chrome OS, PermissionBrokerClient should be called on the UI thread.
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
std::string port_;
DISALLOW_COPY_AND_ASSIGN(SerialIoHandler);
};
} // namespace device
#endif // DEVICE_SERIAL_SERIAL_IO_HANDLER_H_