summaryrefslogtreecommitdiff
path: root/www/chromium-uc/files/hid_connection_fido.cc
diff options
context:
space:
mode:
Diffstat (limited to 'www/chromium-uc/files/hid_connection_fido.cc')
-rw-r--r--www/chromium-uc/files/hid_connection_fido.cc197
1 files changed, 0 insertions, 197 deletions
diff --git a/www/chromium-uc/files/hid_connection_fido.cc b/www/chromium-uc/files/hid_connection_fido.cc
deleted file mode 100644
index dfde857..0000000
--- a/www/chromium-uc/files/hid_connection_fido.cc
+++ /dev/null
@@ -1,197 +0,0 @@
1// Copyright (c) 2020 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#include "services/device/hid/hid_connection_fido.h"
6
7#include "base/bind.h"
8#include "base/files/file_descriptor_watcher_posix.h"
9#include "base/location.h"
10#include "base/numerics/safe_math.h"
11#include "base/posix/eintr_wrapper.h"
12#include "base/single_thread_task_runner.h"
13#include "base/task/post_task.h"
14#include "base/threading/scoped_blocking_call.h"
15#include "base/threading/thread_restrictions.h"
16#include "base/threading/thread_task_runner_handle.h"
17#include "components/device_event_log/device_event_log.h"
18#include "services/device/hid/hid_service.h"
19
20namespace device {
21
22class HidConnectionFido::BlockingTaskHelper {
23public:
24 BlockingTaskHelper(base::ScopedFD fd,
25 scoped_refptr<HidDeviceInfo> device_info,
26 base::WeakPtr<HidConnectionFido> connection)
27 : fd_(std::move(fd)),
28 // Report buffers must always have room for the report ID.
29 report_buffer_size_(device_info->max_input_report_size() + 1),
30 has_report_id_(device_info->has_report_id()), connection_(connection),
31 origin_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
32 DETACH_FROM_SEQUENCE(sequence_checker_);
33 }
34
35 ~BlockingTaskHelper() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
36
37 // Starts the FileDescriptorWatcher that reads input events from the device.
38 // Must be called on a thread that has a base::MessageLoopForIO.
39 void Start() {
40 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
41 base::internal::AssertBlockingAllowed();
42
43 file_watcher_ = base::FileDescriptorWatcher::WatchReadable(
44 fd_.get(), base::BindRepeating(&BlockingTaskHelper::OnFileCanReadWithoutBlocking,
45 base::Unretained(this)));
46 }
47
48 void Write(scoped_refptr<base::RefCountedBytes> buffer,
49 WriteCallback callback) {
50 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
51 base::ScopedBlockingCall scoped_blocking_call(
52 FROM_HERE, base::BlockingType::MAY_BLOCK);
53
54 auto data = buffer->front();
55 size_t size = buffer->size();
56 // if report id is 0, it shouldn't be included
57 if (data[0] == 0) {
58 data++;
59 size--;
60 }
61
62 ssize_t result = HANDLE_EINTR(write(fd_.get(), data, size));
63 bool success = static_cast<size_t>(result) == size;
64 if (!success) {
65 HID_LOG(EVENT) << "HID write failed: " << result << " != " << size;
66 }
67 origin_task_runner_->PostTask(FROM_HERE,
68 base::BindOnce(std::move(callback), success));
69 }
70
71 void GetFeatureReport(uint8_t report_id,
72 scoped_refptr<base::RefCountedBytes> buffer,
73 ReadCallback callback) {
74 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
75 base::ScopedBlockingCall scoped_blocking_call(
76 FROM_HERE, base::BlockingType::MAY_BLOCK);
77 HID_PLOG(EVENT) << "GendFeatureReport not implemented on OpenBSD";
78 origin_task_runner_->PostTask(
79 FROM_HERE, base::BindOnce(std::move(callback), false, nullptr, 0));
80 }
81
82 void SendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
83 WriteCallback callback) {
84 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
85 HID_PLOG(EVENT) << "SendFeatureReport not implemented on OpenBSD";
86 origin_task_runner_->PostTask(FROM_HERE,
87 base::BindOnce(std::move(callback), false));
88 }
89
90private:
91 void OnFileCanReadWithoutBlocking() {
92 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
93
94 scoped_refptr<base::RefCountedBytes> buffer(
95 new base::RefCountedBytes(report_buffer_size_));
96 unsigned char *data = buffer->front();
97 size_t length = report_buffer_size_;
98 if (!has_report_id_) {
99 // OpenBSD will not prefix the buffer with a report ID if report IDs are
100 // not used by the device. Prefix the buffer with 0.
101 *data++ = 0;
102 length--;
103 }
104
105 ssize_t bytes_read = HANDLE_EINTR(read(fd_.get(), data, length));
106 if (bytes_read < 0) {
107 if (errno != EAGAIN) {
108 HID_PLOG(EVENT) << "Read failed";
109 // This assumes that the error is unrecoverable and disables reading
110 // from the device until it has been re-opened.
111 // TODO(reillyg): Investigate starting and stopping the file descriptor
112 // watcher in response to pending read requests so that per-request
113 // errors can be returned to the client.
114 file_watcher_.reset();
115 }
116 return;
117 }
118 if (!has_report_id_) {
119 // Behave as if the byte prefixed above as the the report ID was read.
120 bytes_read++;
121 }
122
123 origin_task_runner_->PostTask(
124 FROM_HERE, base::BindOnce(&HidConnectionFido::ProcessInputReport,
125 connection_, buffer, bytes_read));
126 }
127
128 SEQUENCE_CHECKER(sequence_checker_);
129 base::ScopedFD fd_;
130 const size_t report_buffer_size_;
131 const bool has_report_id_;
132 base::WeakPtr<HidConnectionFido> connection_;
133 const scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
134 std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_;
135
136 DISALLOW_COPY_AND_ASSIGN(BlockingTaskHelper);
137};
138
139HidConnectionFido::HidConnectionFido(
140 scoped_refptr<HidDeviceInfo> device_info, base::ScopedFD fd,
141 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
142 bool allow_protected_reports, bool allow_fido_reports)
143 : HidConnection(device_info, allow_protected_reports, allow_fido_reports),
144 blocking_task_runner_(std::move(blocking_task_runner)),
145 weak_factory_(this),
146 helper_(std::make_unique<BlockingTaskHelper>(
147 std::move(fd), device_info, weak_factory_.GetWeakPtr())) {
148 blocking_task_runner_->PostTask(
149 FROM_HERE, base::BindOnce(&BlockingTaskHelper::Start,
150 base::Unretained(helper_.get())));
151}
152
153HidConnectionFido::~HidConnectionFido() = default;
154
155void HidConnectionFido::PlatformClose() {
156 // By closing the device on the blocking task runner 1) the requirement that
157 // base::ScopedFD is destroyed on a thread where I/O is allowed is satisfied
158 // and 2) any tasks posted to this task runner that refer to this file will
159 // complete before it is closed.
160 blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release());
161}
162
163void HidConnectionFido::PlatformWrite(
164 scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) {
165 blocking_task_runner_->PostTask(
166 FROM_HERE, base::BindOnce(&BlockingTaskHelper::Write,
167 base::Unretained(helper_.get()), buffer,
168 std::move(callback)));
169}
170
171void HidConnectionFido::PlatformGetFeatureReport(uint8_t report_id,
172 ReadCallback callback) {
173 // The first byte of the destination buffer is the report ID being requested
174 // and is overwritten by the feature report.
175 DCHECK_GT(device_info()->max_feature_report_size(), 0u);
176 scoped_refptr<base::RefCountedBytes> buffer(
177 new base::RefCountedBytes(device_info()->max_feature_report_size() + 1));
178 if (report_id != 0)
179 buffer->data()[0] = report_id;
180
181 blocking_task_runner_->PostTask(
182 FROM_HERE, base::BindOnce(&BlockingTaskHelper::GetFeatureReport,
183 base::Unretained(helper_.get()), report_id,
184 buffer, std::move(callback)));
185}
186
187void HidConnectionFido::PlatformSendFeatureReport(
188 scoped_refptr<base::RefCountedBytes> buffer, WriteCallback callback) {
189 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
190 base::BlockingType::MAY_BLOCK);
191 blocking_task_runner_->PostTask(
192 FROM_HERE, base::BindOnce(&BlockingTaskHelper::SendFeatureReport,
193 base::Unretained(helper_.get()), buffer,
194 std::move(callback)));
195}
196
197} // namespace device