usb_device_mac.cc 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 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. #include "services/device/usb/usb_device_mac.h"
  5. #include <IOKit/IOCFPlugIn.h>
  6. #include <IOKit/IOKitLib.h>
  7. #include <IOKit/IOReturn.h>
  8. #include <IOKit/usb/IOUSBLib.h>
  9. #include <utility>
  10. #include "base/mac/foundation_util.h"
  11. #include "base/mac/scoped_ionotificationportref.h"
  12. #include "base/mac/scoped_ioobject.h"
  13. #include "base/mac/scoped_ioplugininterface.h"
  14. #include "components/device_event_log/device_event_log.h"
  15. #include "services/device/usb/usb_descriptors.h"
  16. #include "services/device/usb/usb_device_handle.h"
  17. #include "services/device/usb/usb_device_handle_mac.h"
  18. namespace device {
  19. UsbDeviceMac::UsbDeviceMac(uint64_t entry_id,
  20. mojom::UsbDeviceInfoPtr device_info)
  21. : UsbDevice(std::move(device_info)), entry_id_(entry_id) {}
  22. UsbDeviceMac::~UsbDeviceMac() = default;
  23. void UsbDeviceMac::Open(OpenCallback callback) {
  24. base::ScopedCFTypeRef<CFDictionaryRef> matching_dict(
  25. IORegistryEntryIDMatching(entry_id()));
  26. if (!matching_dict.get()) {
  27. USB_LOG(ERROR) << "Failed to create matching dictionary for ID.";
  28. std::move(callback).Run(nullptr);
  29. return;
  30. }
  31. // IOServiceGetMatchingService consumes a reference to the matching dictionary
  32. // passed to it.
  33. base::mac::ScopedIOObject<io_service_t> usb_device(
  34. IOServiceGetMatchingService(kIOMasterPortDefault,
  35. matching_dict.release()));
  36. if (!usb_device.get()) {
  37. USB_LOG(ERROR) << "IOService not found for ID.";
  38. std::move(callback).Run(nullptr);
  39. return;
  40. }
  41. base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_interface;
  42. int32_t score;
  43. IOReturn kr = IOCreatePlugInInterfaceForService(
  44. usb_device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
  45. plugin_interface.InitializeInto(), &score);
  46. if ((kr != kIOReturnSuccess) || !plugin_interface) {
  47. USB_LOG(ERROR) << "Unable to create a plug-in: " << std::hex << kr;
  48. std::move(callback).Run(nullptr);
  49. return;
  50. }
  51. base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface187> device_interface;
  52. kr = (*plugin_interface)
  53. ->QueryInterface(
  54. plugin_interface.get(),
  55. CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
  56. reinterpret_cast<LPVOID*>(device_interface.InitializeInto()));
  57. if (kr != kIOReturnSuccess || !device_interface) {
  58. USB_LOG(ERROR) << "Couldn’t create a device interface.";
  59. std::move(callback).Run(nullptr);
  60. return;
  61. }
  62. kr = (*device_interface)->USBDeviceOpen(device_interface);
  63. if (kr != kIOReturnSuccess) {
  64. USB_LOG(ERROR) << "Failed to open device: " << std::hex << kr;
  65. std::move(callback).Run(nullptr);
  66. return;
  67. }
  68. auto device_handle = base::MakeRefCounted<UsbDeviceHandleMac>(
  69. this, std::move(device_interface));
  70. handles().push_back(device_handle.get());
  71. std::move(callback).Run(device_handle);
  72. }
  73. } // namespace device