diff options
Diffstat (limited to 'www/chromium-uc/files/hid_connection_fido.cc')
| -rw-r--r-- | www/chromium-uc/files/hid_connection_fido.cc | 197 |
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 | |||
| 20 | namespace device { | ||
| 21 | |||
| 22 | class HidConnectionFido::BlockingTaskHelper { | ||
| 23 | public: | ||
| 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 | |||
| 90 | private: | ||
| 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 | |||
| 139 | HidConnectionFido::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 | |||
| 153 | HidConnectionFido::~HidConnectionFido() = default; | ||
| 154 | |||
| 155 | void 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 | |||
| 163 | void 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 | |||
| 171 | void 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 | |||
| 187 | void 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 | ||
