fido_hid_discovery.cc 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2017 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. #include "device/fido/hid/fido_hid_discovery.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/containers/contains.h"
  8. #include "base/no_destructor.h"
  9. #include "components/device_event_log/device_event_log.h"
  10. #include "device/fido/hid/fido_hid_device.h"
  11. namespace device {
  12. namespace {
  13. // Checks that the supported report sizes of |device| are sufficient for at
  14. // least one byte of non-header data per report and not larger than our maximum
  15. // size.
  16. bool ReportSizesSufficient(const device::mojom::HidDeviceInfo& device) {
  17. return device.max_input_report_size > kHidInitPacketHeaderSize &&
  18. device.max_input_report_size <= kHidMaxPacketSize &&
  19. device.max_output_report_size > kHidInitPacketHeaderSize &&
  20. device.max_output_report_size <= kHidMaxPacketSize;
  21. }
  22. FidoHidDiscovery::HidManagerBinder& GetHidManagerBinder() {
  23. static base::NoDestructor<FidoHidDiscovery::HidManagerBinder> binder;
  24. return *binder;
  25. }
  26. } // namespace
  27. bool operator==(const VidPid& lhs, const VidPid& rhs) {
  28. return lhs.vid == rhs.vid && lhs.pid == rhs.pid;
  29. }
  30. bool operator<(const VidPid& lhs, const VidPid& rhs) {
  31. return lhs.vid < rhs.vid || (lhs.vid == rhs.vid && lhs.pid < rhs.pid);
  32. }
  33. FidoHidDiscovery::FidoHidDiscovery(base::flat_set<VidPid> ignore_list)
  34. : FidoDeviceDiscovery(FidoTransportProtocol::kUsbHumanInterfaceDevice),
  35. ignore_list_(std::move(ignore_list)) {
  36. constexpr uint16_t kFidoUsagePage = 0xf1d0;
  37. filter_.SetUsagePage(kFidoUsagePage);
  38. }
  39. FidoHidDiscovery::~FidoHidDiscovery() = default;
  40. // static
  41. void FidoHidDiscovery::SetHidManagerBinder(HidManagerBinder binder) {
  42. GetHidManagerBinder() = std::move(binder);
  43. }
  44. void FidoHidDiscovery::StartInternal() {
  45. const auto& binder = GetHidManagerBinder();
  46. if (!binder)
  47. return;
  48. binder.Run(hid_manager_.BindNewPipeAndPassReceiver());
  49. hid_manager_->GetDevicesAndSetClient(
  50. receiver_.BindNewEndpointAndPassRemote(),
  51. base::BindOnce(&FidoHidDiscovery::OnGetDevices,
  52. weak_factory_.GetWeakPtr()));
  53. }
  54. void FidoHidDiscovery::DeviceAdded(
  55. device::mojom::HidDeviceInfoPtr device_info) {
  56. // The init packet header is the larger of the headers so we only compare
  57. // against it below.
  58. static_assert(
  59. kHidInitPacketHeaderSize >= kHidContinuationPacketHeaderSize,
  60. "init header is expected to be larger than continuation header");
  61. if (!filter_.Matches(*device_info) || !ReportSizesSufficient(*device_info)) {
  62. return;
  63. }
  64. const VidPid vid_pid{device_info->vendor_id, device_info->product_id};
  65. if (base::Contains(ignore_list_, vid_pid)) {
  66. FIDO_LOG(EVENT) << "Ignoring HID device " << vid_pid.vid << ":"
  67. << vid_pid.pid;
  68. return;
  69. }
  70. AddDevice(std::make_unique<FidoHidDevice>(std::move(device_info),
  71. hid_manager_.get()));
  72. }
  73. void FidoHidDiscovery::DeviceRemoved(
  74. device::mojom::HidDeviceInfoPtr device_info) {
  75. // Ignore non-U2F devices.
  76. if (filter_.Matches(*device_info)) {
  77. RemoveDevice(FidoHidDevice::GetIdForDevice(*device_info));
  78. }
  79. }
  80. void FidoHidDiscovery::DeviceChanged(
  81. device::mojom::HidDeviceInfoPtr device_info) {
  82. // The changed |device_info| may affect how the device should be filtered.
  83. // For instance, it may have been updated from a device with no FIDO U2F
  84. // capabilities to a device with FIDO U2F capabilities.
  85. //
  86. // Try adding it again. If the device is already present in |authenticators_|
  87. // then the updated device will be detected as a duplicate and will not be
  88. // added.
  89. //
  90. // The FidoHidDevice object will retain the old device info. This is fine
  91. // since it does not rely on any HidDeviceInfo members that could change.
  92. DeviceAdded(std::move(device_info));
  93. }
  94. void FidoHidDiscovery::OnGetDevices(
  95. std::vector<device::mojom::HidDeviceInfoPtr> device_infos) {
  96. for (auto& device_info : device_infos)
  97. DeviceAdded(std::move(device_info));
  98. NotifyDiscoveryStarted(true);
  99. }
  100. } // namespace device