diff options
Diffstat (limited to 'devel/electron33/files/patch-services_device_hid_hid__service__freebsd.cc')
-rw-r--r-- | devel/electron33/files/patch-services_device_hid_hid__service__freebsd.cc | 398 |
1 files changed, 0 insertions, 398 deletions
diff --git a/devel/electron33/files/patch-services_device_hid_hid__service__freebsd.cc b/devel/electron33/files/patch-services_device_hid_hid__service__freebsd.cc deleted file mode 100644 index 0e12715a6312..000000000000 --- a/devel/electron33/files/patch-services_device_hid_hid__service__freebsd.cc +++ /dev/null @@ -1,398 +0,0 @@ ---- services/device/hid/hid_service_freebsd.cc.orig 2023-04-10 14:02:12 UTC -+++ services/device/hid/hid_service_freebsd.cc -@@ -0,0 +1,395 @@ -+// 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. -+ -+#include "services/device/hid/hid_service_freebsd.h" -+ -+#include <dev/usb/usb_ioctl.h> -+#include <stdint.h> -+#include <sys/socket.h> -+#include <sys/un.h> -+ -+#include <set> -+#include <string> -+#include <vector> -+ -+#include "base/files/file_descriptor_watcher_posix.h" -+#include "base/files/file_enumerator.h" -+#include "base/files/file_util.h" -+#include "base/files/file.h" -+#include "base/location.h" -+#include "base/logging.h" -+#include "base/posix/eintr_wrapper.h" -+#include "base/stl_util.h" -+#include "base/strings/pattern.h" -+#include "base/strings/stringprintf.h" -+#include "base/strings/sys_string_conversions.h" -+#include "base/strings/string_util.h" -+#include "base/strings/string_split.h" -+#include "base/task/single_thread_task_runner.h" -+#include "base/task/thread_pool.h" -+#include "base/threading/scoped_blocking_call.h" -+#include "base/threading/thread_restrictions.h" -+#include "components/device_event_log/device_event_log.h" -+#include "services/device/hid/hid_connection_freebsd.h" -+ -+const int kMaxPermissionChecks = 5; -+ -+namespace device { -+ -+struct HidServiceFreeBSD::ConnectParams { -+ ConnectParams(scoped_refptr<HidDeviceInfo> device_info, -+ bool allow_protected_reports, -+ bool allow_fido_reports, -+ ConnectCallback callback) -+ : device_info(std::move(device_info)), -+ allow_protected_reports(allow_protected_reports), -+ allow_fido_reports(allow_fido_reports), -+ callback(std::move(callback)), -+ task_runner(base::SequencedTaskRunner::GetCurrentDefault()), -+ blocking_task_runner( -+ base::ThreadPool::CreateSequencedTaskRunner(kBlockingTaskTraits)) {} -+ ~ConnectParams() {} -+ -+ scoped_refptr<HidDeviceInfo> device_info; -+ bool allow_protected_reports; -+ bool allow_fido_reports; -+ ConnectCallback callback; -+ scoped_refptr<base::SequencedTaskRunner> task_runner; -+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner; -+ base::ScopedFD fd; -+}; -+ -+class HidServiceFreeBSD::BlockingTaskRunnerHelper { -+ public: -+ BlockingTaskRunnerHelper(base::WeakPtr<HidServiceFreeBSD> service) -+ : service_(std::move(service)), -+ task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) { -+ DETACH_FROM_SEQUENCE(sequence_checker_); -+ -+ timer_.reset(new base::RepeatingTimer()); -+ devd_buffer_ = new net::IOBufferWithSize(1024); -+ } -+ -+ BlockingTaskRunnerHelper(const BlockingTaskRunnerHelper&) = delete; -+ BlockingTaskRunnerHelper& operator=(const BlockingTaskRunnerHelper&) = delete; -+ -+ ~BlockingTaskRunnerHelper() { -+ } -+ -+ void Start() { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ -+ const base::FilePath kDevRoot("/dev"); -+ const std::string kUHIDPattern("/dev/uhid*"); -+ -+ base::FileEnumerator enumerator(kDevRoot, false, base::FileEnumerator::FILES); -+ do { -+ const base::FilePath next_device_path(enumerator.Next()); -+ const std::string next_device = next_device_path.value(); -+ if (next_device.empty()) -+ break; -+ -+ if (base::MatchPattern(next_device, kUHIDPattern)) -+ OnDeviceAdded(next_device.substr(5)); -+ } while (true); -+ -+ SetupDevdMonitor(); -+ -+ task_runner_->PostTask( -+ FROM_HERE, -+ base::BindOnce(&HidServiceFreeBSD::FirstEnumerationComplete, service_)); -+ } -+ -+ bool HaveReadWritePermissions(std::string device_id) { -+ std::string device_node = "/dev/" + device_id; -+ base::internal::AssertBlockingAllowed(); -+ -+ base::FilePath device_path(device_node); -+ base::File device_file; -+ int flags = -+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; -+ device_file.Initialize(device_path, flags); -+ if (!device_file.IsValid()) -+ return false; -+ -+ return true; -+ } -+ -+ void OnDeviceAdded(std::string device_id) { -+ base::ScopedBlockingCall scoped_blocking_call( -+ FROM_HERE, base::BlockingType::MAY_BLOCK); -+ std::string device_node = "/dev/" + device_id; -+ uint16_t vendor_id = 0xffff; -+ uint16_t product_id = 0xffff; -+ std::string product_name = ""; -+ std::string serial_number = ""; -+ -+ std::vector<uint8_t> report_descriptor; -+ -+ base::internal::AssertBlockingAllowed(); -+ -+ base::FilePath device_path(device_node); -+ base::File device_file; -+ int flags = -+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; -+ device_file.Initialize(device_path, flags); -+ if (!device_file.IsValid()) { -+ HID_LOG(ERROR) << "Failed to open '" << device_node -+ << "': " -+ << base::File::ErrorToString(device_file.error_details()); -+ return; -+ } -+ -+ base::ScopedFD fd; -+ fd.reset(device_file.TakePlatformFile()); -+ -+ struct usb_gen_descriptor ugd; -+ ugd.ugd_data = NULL; -+ ugd.ugd_maxlen = 0xffff; -+ int result = HANDLE_EINTR( -+ ioctl(fd.get(), USB_GET_REPORT_DESC, &ugd)); -+ -+ if (result < 0) { -+ HID_LOG(ERROR) << "Failed to get report descriptor size"; -+ return; -+ } -+ -+ report_descriptor.resize(ugd.ugd_actlen); -+ -+ ugd.ugd_data = report_descriptor.data(); -+ ugd.ugd_maxlen = ugd.ugd_actlen; -+ result = HANDLE_EINTR( -+ ioctl(fd.get(), USB_GET_REPORT_DESC, &ugd)); -+ -+ if (result < 0) { -+ HID_LOG(ERROR) << "Failed to get report descriptor"; -+ return; -+ } -+ -+ scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo( -+ device_id, -+ /*physical_device_id*/"", -+ vendor_id, -+ product_id, -+ product_name, -+ serial_number, -+ device::mojom::HidBusType::kHIDBusTypeUSB, -+ report_descriptor, -+ device_node)); -+ -+ task_runner_->PostTask(FROM_HERE, base::BindOnce(&HidServiceFreeBSD::AddDevice, -+ service_, device_info)); -+ } -+ -+ void OnDeviceRemoved(std::string device_id) { -+ base::ScopedBlockingCall scoped_blocking_call( -+ FROM_HERE, base::BlockingType::MAY_BLOCK); -+ task_runner_->PostTask( -+ FROM_HERE, base::BindOnce(&HidServiceFreeBSD::RemoveDevice, service_, -+ device_id)); -+ } -+ -+ private: -+ -+ void CheckPendingPermissionChange() { -+ base::internal::AssertBlockingAllowed(); -+ std::map<std::string, int>::iterator it; -+ for (it = permissions_checks_attempts_.begin(); it != permissions_checks_attempts_.end();) { -+ std::string device_name = it->first; -+ bool keep = true; -+ if (HaveReadWritePermissions(device_name)) { -+ OnDeviceAdded(device_name); -+ keep = false; -+ } -+ else if (it->second-- <= 0) { -+ HID_LOG(ERROR) << "Still don't have write permissions to '" << device_name -+ << "' after " << kMaxPermissionChecks << " attempts"; -+ keep = false; -+ } -+ -+ if (keep) -+ ++it; -+ else -+ permissions_checks_attempts_.erase(it++); -+ } -+ -+ if (permissions_checks_attempts_.empty()) -+ timer_->Stop(); -+ } -+ -+ void SetupDevdMonitor() { -+ base::internal::AssertBlockingAllowed(); -+ -+ int devd_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); -+ if (devd_fd < 0) -+ return; -+ -+ struct sockaddr_un sa; -+ -+ sa.sun_family = AF_UNIX; -+ strlcpy(sa.sun_path, "/var/run/devd.seqpacket.pipe", sizeof(sa.sun_path)); -+ if (connect(devd_fd, (struct sockaddr *) &sa, sizeof(sa)) < 0) { -+ close(devd_fd); -+ return; -+ } -+ -+ devd_fd_.reset(devd_fd); -+ file_watcher_ = base::FileDescriptorWatcher::WatchReadable( -+ devd_fd_.get(), base::BindRepeating(&BlockingTaskRunnerHelper::OnDevdMessageCanBeRead, -+ base::Unretained(this))); -+ } -+ -+ void OnDevdMessageCanBeRead() { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ ssize_t bytes_read = HANDLE_EINTR(recv(devd_fd_.get(), devd_buffer_->data(), -+ devd_buffer_->size() - 1, MSG_WAITALL)); -+ if (bytes_read < 0) { -+ if (errno != EAGAIN) { -+ HID_LOG(ERROR) << "Read failed"; -+ file_watcher_.reset(); -+ } -+ return; -+ } -+ -+ devd_buffer_->data()[bytes_read] = 0; -+ char *data = devd_buffer_->data(); -+ // It may take some time for devd to change permissions -+ // on /dev/uhidX node. So do not fail immediately if -+ // open fail. Retry each second for kMaxPermissionChecks -+ // times before giving up entirely -+ if (base::StartsWith(data, "+uhid", base::CompareCase::SENSITIVE)) { -+ std::vector<std::string> parts = base::SplitString( -+ data, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); -+ if (!parts.empty()) { -+ std::string device_name = parts[0].substr(1); // skip '+' -+ if (HaveReadWritePermissions(device_name)) -+ OnDeviceAdded(parts[0].substr(1)); -+ else { -+ // Do not re-add to checks -+ if (permissions_checks_attempts_.find(device_name) == permissions_checks_attempts_.end()) { -+ permissions_checks_attempts_.insert(std::pair<std::string, int>(device_name, kMaxPermissionChecks)); -+ timer_->Start(FROM_HERE, base::Seconds(1), -+ this, &BlockingTaskRunnerHelper::CheckPendingPermissionChange); -+ } -+ } -+ } -+ } -+ -+ if (base::StartsWith(data, "-uhid", base::CompareCase::SENSITIVE)) { -+ std::vector<std::string> parts = base::SplitString( -+ data, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); -+ if (!parts.empty()) { -+ std::string device_name = parts[0].substr(1); // skip '-' -+ auto it = permissions_checks_attempts_.find(device_name); -+ if (it != permissions_checks_attempts_.end()) { -+ permissions_checks_attempts_.erase(it); -+ if (permissions_checks_attempts_.empty()) -+ timer_->Stop(); -+ } -+ OnDeviceRemoved(parts[0].substr(1)); -+ } -+ } -+ } -+ -+ SEQUENCE_CHECKER(sequence_checker_); -+ -+ // This weak pointer is only valid when checked on this task runner. -+ base::WeakPtr<HidServiceFreeBSD> service_; -+ scoped_refptr<base::SequencedTaskRunner> task_runner_; -+ std::unique_ptr<base::FileDescriptorWatcher::Controller> file_watcher_; -+ std::unique_ptr<base::RepeatingTimer> timer_; -+ base::ScopedFD devd_fd_; -+ scoped_refptr<net::IOBufferWithSize> devd_buffer_; -+ std::map<std::string, int> permissions_checks_attempts_; -+}; -+ -+HidServiceFreeBSD::HidServiceFreeBSD() -+ : blocking_task_runner_( -+ base::ThreadPool::CreateSequencedTaskRunner(kBlockingTaskTraits)), -+ helper_(nullptr, base::OnTaskRunnerDeleter(blocking_task_runner_)) { -+ helper_.reset(new BlockingTaskRunnerHelper(weak_factory_.GetWeakPtr())); -+ blocking_task_runner_->PostTask( -+ FROM_HERE, -+ base::BindOnce(&BlockingTaskRunnerHelper::Start, base::Unretained(helper_.get()))); -+} -+ -+HidServiceFreeBSD::~HidServiceFreeBSD() { -+ blocking_task_runner_->DeleteSoon(FROM_HERE, helper_.release()); -+} -+ -+base::WeakPtr<HidService> HidServiceFreeBSD::GetWeakPtr() { -+ return weak_factory_.GetWeakPtr(); -+} -+ -+// static -+void HidServiceFreeBSD::OpenOnBlockingThread( -+ std::unique_ptr<ConnectParams> params) { -+ base::ScopedBlockingCall scoped_blocking_call( -+ FROM_HERE, base::BlockingType::MAY_BLOCK); -+ scoped_refptr<base::SequencedTaskRunner> task_runner = params->task_runner; -+ -+ base::FilePath device_path(params->device_info->device_node()); -+ base::File device_file; -+ int flags = -+ base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE; -+ device_file.Initialize(device_path, flags); -+ if (!device_file.IsValid()) { -+ HID_LOG(EVENT) << "Failed to open '" << params->device_info->device_node() -+ << "': " -+ << base::File::ErrorToString(device_file.error_details()); -+ task_runner->PostTask(FROM_HERE, -+ base::BindOnce(std::move(params->callback), nullptr)); -+ return; -+ } -+ params->fd.reset(device_file.TakePlatformFile()); -+ task_runner->PostTask(FROM_HERE, base::BindOnce(&HidServiceFreeBSD::FinishOpen, -+ std::move(params))); -+} -+ -+void HidServiceFreeBSD::Connect(const std::string& device_guid, -+ bool allow_protected_reports, -+ bool allow_fido_reports, -+ ConnectCallback callback) { -+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); -+ -+ const auto& map_entry = devices().find(device_guid); -+ if (map_entry == devices().end()) { -+ base::SequencedTaskRunner::GetCurrentDefault()->PostTask( -+ FROM_HERE, base::BindOnce(std::move(callback), nullptr)); -+ return; -+ } -+ -+ scoped_refptr<HidDeviceInfo> device_info = map_entry->second; -+ -+ auto params = std::make_unique<ConnectParams>(device_info, -+ allow_protected_reports, -+ allow_fido_reports, -+ std::move(callback)); -+ scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = -+ params->blocking_task_runner; -+ -+ blocking_task_runner->PostTask( -+ FROM_HERE, base::BindOnce(&HidServiceFreeBSD::OpenOnBlockingThread, -+ std::move(params))); -+} -+ -+// static -+void HidServiceFreeBSD::FinishOpen(std::unique_ptr<ConnectParams> params) { -+ DCHECK(params->fd.is_valid()); -+ -+ if (!base::SetNonBlocking(params->fd.get())) { -+ HID_PLOG(ERROR) << "Failed to set the non-blocking flag on the device fd"; -+ std::move(params->callback).Run(nullptr); -+ } -+ -+ std::move(params->callback).Run(base::MakeRefCounted<HidConnectionFreeBSD>( -+ std::move(params->device_info), -+ std::move(params->fd), -+ std::move(params->blocking_task_runner), -+ params->allow_protected_reports, -+ params->allow_fido_reports -+ )); -+} -+ -+} // namespace device |