usb_device_impl.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Copyright 2014 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_impl.h"
  5. #include <fcntl.h>
  6. #include <stddef.h>
  7. #include <algorithm>
  8. #include "base/bind.h"
  9. #include "base/location.h"
  10. #include "base/posix/eintr_wrapper.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/task/single_thread_task_runner.h"
  13. #include "base/threading/scoped_blocking_call.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "build/build_config.h"
  16. #include "components/device_event_log/device_event_log.h"
  17. #include "services/device/usb/usb_context.h"
  18. #include "services/device/usb/usb_descriptors.h"
  19. #include "services/device/usb/usb_device_handle_impl.h"
  20. #include "services/device/usb/usb_error.h"
  21. #include "services/device/usb/usb_service.h"
  22. #include "third_party/libusb/src/libusb/libusb.h"
  23. namespace device {
  24. UsbDeviceImpl::UsbDeviceImpl(ScopedLibusbDeviceRef platform_device,
  25. const libusb_device_descriptor& descriptor)
  26. : UsbDevice(descriptor.bcdUSB,
  27. descriptor.bDeviceClass,
  28. descriptor.bDeviceSubClass,
  29. descriptor.bDeviceProtocol,
  30. descriptor.idVendor,
  31. descriptor.idProduct,
  32. descriptor.bcdDevice,
  33. std::u16string(),
  34. std::u16string(),
  35. std::u16string(),
  36. libusb_get_bus_number(platform_device.get()),
  37. libusb_get_port_number(platform_device.get())),
  38. platform_device_(std::move(platform_device)) {
  39. CHECK(platform_device_.IsValid()) << "platform_device must be valid";
  40. ReadAllConfigurations();
  41. RefreshActiveConfiguration();
  42. }
  43. UsbDeviceImpl::~UsbDeviceImpl() {
  44. // The destructor must be safe to call from any thread.
  45. }
  46. void UsbDeviceImpl::Open(OpenCallback callback) {
  47. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  48. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner =
  49. UsbService::CreateBlockingTaskRunner();
  50. blocking_task_runner->PostTask(
  51. FROM_HERE,
  52. base::BindOnce(&UsbDeviceImpl::OpenOnBlockingThread, this,
  53. std::move(callback), base::ThreadTaskRunnerHandle::Get(),
  54. blocking_task_runner));
  55. }
  56. void UsbDeviceImpl::ReadAllConfigurations() {
  57. libusb_device_descriptor device_descriptor;
  58. int rv = libusb_get_device_descriptor(platform_device(), &device_descriptor);
  59. if (rv == LIBUSB_SUCCESS) {
  60. UsbDeviceDescriptor usb_descriptor;
  61. for (uint8_t i = 0; i < device_descriptor.bNumConfigurations; ++i) {
  62. unsigned char* buffer;
  63. rv = libusb_get_raw_config_descriptor(platform_device(), i, &buffer);
  64. if (rv < 0) {
  65. USB_LOG(EVENT) << "Failed to get config descriptor: "
  66. << ConvertPlatformUsbErrorToString(rv);
  67. continue;
  68. }
  69. if (!usb_descriptor.Parse(base::make_span(buffer, rv)))
  70. USB_LOG(EVENT) << "Config descriptor index " << i << " was corrupt.";
  71. free(buffer);
  72. }
  73. // The only populated field in |usb_descriptor| is the parsed configuration
  74. // descriptor info.
  75. device_info_->configurations =
  76. std::move(usb_descriptor.device_info->configurations);
  77. } else {
  78. USB_LOG(EVENT) << "Failed to get device descriptor: "
  79. << ConvertPlatformUsbErrorToString(rv);
  80. }
  81. }
  82. void UsbDeviceImpl::RefreshActiveConfiguration() {
  83. uint8_t config_value;
  84. int rv = libusb_get_active_config_value(platform_device(), &config_value);
  85. if (rv != LIBUSB_SUCCESS) {
  86. USB_LOG(EVENT) << "Failed to get active configuration: "
  87. << ConvertPlatformUsbErrorToString(rv);
  88. return;
  89. }
  90. ActiveConfigurationChanged(config_value);
  91. }
  92. void UsbDeviceImpl::OpenOnBlockingThread(
  93. OpenCallback callback,
  94. scoped_refptr<base::TaskRunner> task_runner,
  95. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
  96. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  97. base::BlockingType::MAY_BLOCK);
  98. libusb_device_handle* handle = nullptr;
  99. const int rv = libusb_open(platform_device(), &handle);
  100. if (LIBUSB_SUCCESS == rv) {
  101. ScopedLibusbDeviceHandle scoped_handle(handle,
  102. platform_device_.GetContext());
  103. task_runner->PostTask(
  104. FROM_HERE,
  105. base::BindOnce(&UsbDeviceImpl::Opened, this, std::move(scoped_handle),
  106. std::move(callback), blocking_task_runner));
  107. } else {
  108. USB_LOG(EVENT) << "Failed to open device: "
  109. << ConvertPlatformUsbErrorToString(rv);
  110. task_runner->PostTask(FROM_HERE,
  111. base::BindOnce(std::move(callback), nullptr));
  112. }
  113. }
  114. void UsbDeviceImpl::Opened(
  115. ScopedLibusbDeviceHandle platform_handle,
  116. OpenCallback callback,
  117. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) {
  118. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  119. scoped_refptr<UsbDeviceHandle> device_handle = new UsbDeviceHandleImpl(
  120. this, std::move(platform_handle), blocking_task_runner);
  121. handles().push_back(device_handle.get());
  122. std::move(callback).Run(device_handle);
  123. }
  124. } // namespace device