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.
5 #include "device/usb/usb_service_impl.h"
11 #include "base/barrier_closure.h"
12 #include "base/bind.h"
13 #include "base/location.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "components/device_event_log/device_event_log.h"
21 #include "device/usb/usb_device_handle.h"
22 #include "device/usb/usb_error.h"
23 #include "third_party/libusb/src/libusb/libusb.h"
29 #include "base/strings/string_util.h"
33 #include "device/udev_linux/scoped_udev.h"
42 // Wrapper around a HDEVINFO that automatically destroys it.
43 class ScopedDeviceInfoList
{
45 explicit ScopedDeviceInfoList(HDEVINFO handle
) : handle_(handle
) {}
47 ~ScopedDeviceInfoList() {
49 SetupDiDestroyDeviceInfoList(handle_
);
53 bool valid() { return handle_
!= INVALID_HANDLE_VALUE
; }
55 HDEVINFO
get() { return handle_
; }
60 DISALLOW_COPY_AND_ASSIGN(ScopedDeviceInfoList
);
63 // Wrapper around an SP_DEVINFO_DATA that initializes it properly and
64 // automatically deletes it.
65 class ScopedDeviceInfo
{
68 memset(&dev_info_data_
, 0, sizeof(dev_info_data_
));
69 dev_info_data_
.cbSize
= sizeof(dev_info_data_
);
73 if (dev_info_set_
!= INVALID_HANDLE_VALUE
) {
74 SetupDiDeleteDeviceInfo(dev_info_set_
, &dev_info_data_
);
78 // Once the SP_DEVINFO_DATA has been populated it must be freed using the
79 // HDEVINFO it was created from.
80 void set_valid(HDEVINFO dev_info_set
) {
81 DCHECK(dev_info_set_
== INVALID_HANDLE_VALUE
);
82 DCHECK(dev_info_set
!= INVALID_HANDLE_VALUE
);
83 dev_info_set_
= dev_info_set
;
86 PSP_DEVINFO_DATA
get() { return &dev_info_data_
; }
89 HDEVINFO dev_info_set_
= INVALID_HANDLE_VALUE
;
90 SP_DEVINFO_DATA dev_info_data_
;
93 bool IsWinUsbInterface(const std::string
& device_path
) {
94 ScopedDeviceInfoList
dev_info_list(SetupDiCreateDeviceInfoList(NULL
, NULL
));
95 if (!dev_info_list
.valid()) {
96 USB_PLOG(ERROR
) << "Failed to create a device information set";
100 // This will add the device to |dev_info_list| so we can query driver info.
101 if (!SetupDiOpenDeviceInterfaceA(dev_info_list
.get(), device_path
.c_str(), 0,
103 USB_PLOG(ERROR
) << "Failed to get device interface data for "
108 ScopedDeviceInfo dev_info
;
109 if (!SetupDiEnumDeviceInfo(dev_info_list
.get(), 0, dev_info
.get())) {
110 USB_PLOG(ERROR
) << "Failed to get device info for " << device_path
;
113 dev_info
.set_valid(dev_info_list
.get());
117 if (!SetupDiGetDeviceRegistryPropertyA(dev_info_list
.get(), dev_info
.get(),
118 SPDRP_SERVICE
, ®_data_type
,
119 &buffer
[0], sizeof buffer
, NULL
)) {
120 USB_PLOG(ERROR
) << "Failed to get device service property";
123 if (reg_data_type
!= REG_SZ
) {
124 USB_LOG(ERROR
) << "Unexpected data type for driver service: "
129 USB_LOG(DEBUG
) << "Driver for " << device_path
<< " is " << buffer
<< ".";
130 if (base::StartsWith(reinterpret_cast<const char*>(buffer
), "WinUSB",
131 base::CompareCase::INSENSITIVE_ASCII
))
138 void GetDeviceListOnBlockingThread(
139 const std::string
& new_device_path
,
140 scoped_refptr
<UsbContext
> usb_context
,
141 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
142 base::Callback
<void(libusb_device
**, size_t)> callback
) {
144 if (!new_device_path
.empty()) {
145 if (!IsWinUsbInterface(new_device_path
)) {
146 // Wait to call libusb_get_device_list until libusb will be able to find
147 // a WinUSB interface for the device.
148 task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, nullptr, 0));
152 #endif // defined(OS_WIN)
154 libusb_device
** platform_devices
= NULL
;
155 const ssize_t device_count
=
156 libusb_get_device_list(usb_context
->context(), &platform_devices
);
157 if (device_count
< 0) {
158 USB_LOG(ERROR
) << "Failed to get device list: "
159 << ConvertPlatformUsbErrorToString(device_count
);
160 task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, nullptr, 0));
164 task_runner
->PostTask(FROM_HERE
,
165 base::Bind(callback
, platform_devices
, device_count
));
168 #if defined(USE_UDEV)
170 void EnumerateUdevDevice(scoped_refptr
<UsbDeviceImpl
> device
,
171 scoped_refptr
<base::SequencedTaskRunner
> task_runner
,
172 const base::Closure
& success_closure
,
173 const base::Closure
& failure_closure
) {
174 ScopedUdevPtr
udev(udev_new());
175 ScopedUdevEnumeratePtr
udev_enumerate(udev_enumerate_new(udev
.get()));
177 udev_enumerate_add_match_subsystem(udev_enumerate
.get(), "usb");
178 if (udev_enumerate_scan_devices(udev_enumerate
.get()) != 0) {
179 task_runner
->PostTask(FROM_HERE
, failure_closure
);
183 std::string bus_number
=
184 base::IntToString(libusb_get_bus_number(device
->platform_device()));
185 std::string device_address
=
186 base::IntToString(libusb_get_device_address(device
->platform_device()));
187 udev_list_entry
* devices
=
188 udev_enumerate_get_list_entry(udev_enumerate
.get());
189 for (udev_list_entry
* i
= devices
; i
!= NULL
;
190 i
= udev_list_entry_get_next(i
)) {
191 ScopedUdevDevicePtr
udev_device(
192 udev_device_new_from_syspath(udev
.get(), udev_list_entry_get_name(i
)));
195 udev_device_get_sysattr_value(udev_device
.get(), "busnum");
196 if (!value
|| bus_number
!= value
) {
199 value
= udev_device_get_sysattr_value(udev_device
.get(), "devnum");
200 if (!value
|| device_address
!= value
) {
204 value
= udev_device_get_sysattr_value(udev_device
.get(), "manufacturer");
206 device
->set_manufacturer_string(base::UTF8ToUTF16(value
));
208 value
= udev_device_get_sysattr_value(udev_device
.get(), "product");
210 device
->set_product_string(base::UTF8ToUTF16(value
));
212 value
= udev_device_get_sysattr_value(udev_device
.get(), "serial");
214 device
->set_serial_number(base::UTF8ToUTF16(value
));
217 value
= udev_device_get_devnode(udev_device
.get());
219 device
->set_device_path(value
);
220 task_runner
->PostTask(FROM_HERE
, success_closure
);
228 task_runner
->PostTask(FROM_HERE
, failure_closure
);
233 void OnReadStringDescriptor(
234 const base::Callback
<void(const base::string16
&)>& callback
,
235 UsbTransferStatus status
,
236 scoped_refptr
<net::IOBuffer
> buffer
,
238 if (status
!= USB_TRANSFER_COMPLETED
|| length
< 2) {
239 callback
.Run(base::string16());
241 // Take the lesser of the length of data returned by the device and the
242 // length reported in the descriptor.
243 size_t internal_length
= reinterpret_cast<uint8
*>(buffer
->data())[0];
244 length
= std::min(length
, internal_length
);
245 // Cut off the first 2 bytes of the descriptor which are the length and
246 // descriptor type (always STRING).
247 callback
.Run(base::string16(
248 reinterpret_cast<base::char16
*>(buffer
->data() + 2), length
/ 2 - 1));
252 void ReadStringDescriptor(
253 scoped_refptr
<UsbDeviceHandle
> device_handle
,
256 const base::Callback
<void(const base::string16
&)>& callback
) {
257 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(256);
258 device_handle
->ControlTransfer(
259 USB_DIRECTION_INBOUND
, UsbDeviceHandle::STANDARD
, UsbDeviceHandle::DEVICE
,
260 6 /* GET_DESCRIPTOR */, 3 /* STRING */ << 8 | index
, language_id
, buffer
,
261 256, 60, base::Bind(&OnReadStringDescriptor
, callback
));
264 void CloseHandleAndRunContinuation(scoped_refptr
<UsbDeviceHandle
> device_handle
,
265 const base::Closure
& continuation
) {
266 device_handle
->Close();
270 void SaveStringAndRunContinuation(
271 const base::Callback
<void(const base::string16
&)>& save_callback
,
272 const base::Closure
& continuation
,
273 const base::string16
& value
) {
274 if (!value
.empty()) {
275 save_callback
.Run(value
);
280 void OnReadLanguageIds(scoped_refptr
<UsbDeviceHandle
> device_handle
,
284 const base::Closure
& success_closure
,
285 const base::string16
& languages
) {
286 // Default to English unless the device provides a language and then just pick
288 uint16 language_id
= 0x0409;
289 if (!languages
.empty()) {
290 language_id
= languages
[0];
293 scoped_refptr
<UsbDeviceImpl
> device
=
294 static_cast<UsbDeviceImpl
*>(device_handle
->GetDevice().get());
295 base::Closure continuation
=
296 base::BarrierClosure(3, base::Bind(&CloseHandleAndRunContinuation
,
297 device_handle
, success_closure
));
299 if (manufacturer
== 0) {
302 ReadStringDescriptor(
303 device_handle
, manufacturer
, language_id
,
304 base::Bind(&SaveStringAndRunContinuation
,
305 base::Bind(&UsbDeviceImpl::set_manufacturer_string
, device
),
312 ReadStringDescriptor(
313 device_handle
, product
, language_id
,
314 base::Bind(&SaveStringAndRunContinuation
,
315 base::Bind(&UsbDeviceImpl::set_product_string
, device
),
319 if (serial_number
== 0) {
322 ReadStringDescriptor(
323 device_handle
, serial_number
, language_id
,
324 base::Bind(&SaveStringAndRunContinuation
,
325 base::Bind(&UsbDeviceImpl::set_serial_number
, device
),
330 void ReadDeviceLanguage(uint8 manufacturer
,
333 const base::Closure
& success_closure
,
334 const base::Closure
& failure_closure
,
335 scoped_refptr
<UsbDeviceHandle
> device_handle
) {
337 ReadStringDescriptor(
339 base::Bind(&OnReadLanguageIds
, device_handle
, manufacturer
, product
,
340 serial_number
, success_closure
));
342 failure_closure
.Run();
351 UsbService
* UsbServiceImpl::Create(
352 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
) {
353 PlatformUsbContext context
= NULL
;
354 const int rv
= libusb_init(&context
);
355 if (rv
!= LIBUSB_SUCCESS
) {
356 USB_LOG(ERROR
) << "Failed to initialize libusb: "
357 << ConvertPlatformUsbErrorToString(rv
);
364 return new UsbServiceImpl(context
, blocking_task_runner
);
367 UsbServiceImpl::UsbServiceImpl(
368 PlatformUsbContext context
,
369 scoped_refptr
<base::SequencedTaskRunner
> blocking_task_runner
)
370 : context_(new UsbContext(context
)),
371 task_runner_(base::ThreadTaskRunnerHandle::Get()),
372 blocking_task_runner_(blocking_task_runner
),
374 device_observer_(this),
376 weak_factory_(this) {
377 base::MessageLoop::current()->AddDestructionObserver(this);
379 int rv
= libusb_hotplug_register_callback(
381 static_cast<libusb_hotplug_event
>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
|
382 LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
),
383 static_cast<libusb_hotplug_flag
>(0), LIBUSB_HOTPLUG_MATCH_ANY
,
384 LIBUSB_HOTPLUG_MATCH_ANY
, LIBUSB_HOTPLUG_MATCH_ANY
,
385 &UsbServiceImpl::HotplugCallback
, this, &hotplug_handle_
);
386 if (rv
== LIBUSB_SUCCESS
) {
387 hotplug_enabled_
= true;
392 DeviceMonitorWin
* device_monitor
= DeviceMonitorWin::GetForAllInterfaces();
393 if (device_monitor
) {
394 device_observer_
.Add(device_monitor
);
399 UsbServiceImpl::~UsbServiceImpl() {
400 base::MessageLoop::current()->RemoveDestructionObserver(this);
402 if (hotplug_enabled_
) {
403 libusb_hotplug_deregister_callback(context_
->context(), hotplug_handle_
);
405 for (const auto& map_entry
: devices_
) {
406 map_entry
.second
->OnDisconnect();
410 scoped_refptr
<UsbDevice
> UsbServiceImpl::GetDevice(const std::string
& guid
) {
411 DCHECK(CalledOnValidThread());
412 DeviceMap::iterator it
= devices_
.find(guid
);
413 if (it
!= devices_
.end()) {
419 void UsbServiceImpl::GetDevices(const GetDevicesCallback
& callback
) {
420 DCHECK(CalledOnValidThread());
422 if (hotplug_enabled_
&& !enumeration_in_progress_
) {
423 // The device list is updated live when hotplug events are supported.
424 std::vector
<scoped_refptr
<UsbDevice
>> devices
;
425 for (const auto& map_entry
: devices_
) {
426 devices
.push_back(map_entry
.second
);
428 callback
.Run(devices
);
430 pending_enumeration_callbacks_
.push_back(callback
);
437 void UsbServiceImpl::OnDeviceAdded(const GUID
& class_guid
,
438 const std::string
& device_path
) {
439 // Only the root node of a composite USB device has the class GUID
440 // GUID_DEVINTERFACE_USB_DEVICE but we want to wait until WinUSB is loaded.
441 // This first pass filter will catch anything that's sitting on the USB bus
442 // (including devices on 3rd party USB controllers) to avoid the more
443 // expensive driver check that needs to be done on the FILE thread.
444 if (device_path
.find("usb") != std::string::npos
) {
445 pending_path_enumerations_
.push(device_path
);
450 void UsbServiceImpl::OnDeviceRemoved(const GUID
& class_guid
,
451 const std::string
& device_path
) {
452 // The root USB device node is removed last.
453 if (class_guid
== GUID_DEVINTERFACE_USB_DEVICE
) {
460 void UsbServiceImpl::WillDestroyCurrentMessageLoop() {
461 DCHECK(CalledOnValidThread());
465 void UsbServiceImpl::RefreshDevices() {
466 DCHECK(CalledOnValidThread());
468 if (enumeration_in_progress_
) {
472 enumeration_in_progress_
= true;
473 DCHECK(devices_being_enumerated_
.empty());
475 std::string device_path
;
476 if (!pending_path_enumerations_
.empty()) {
477 device_path
= pending_path_enumerations_
.front();
478 pending_path_enumerations_
.pop();
481 blocking_task_runner_
->PostTask(
483 base::Bind(&GetDeviceListOnBlockingThread
, device_path
, context_
,
484 task_runner_
, base::Bind(&UsbServiceImpl::OnDeviceList
,
485 weak_factory_
.GetWeakPtr())));
488 void UsbServiceImpl::OnDeviceList(libusb_device
** platform_devices
,
489 size_t device_count
) {
490 DCHECK(CalledOnValidThread());
491 if (!platform_devices
) {
492 RefreshDevicesComplete();
496 base::Closure refresh_complete
=
497 base::BarrierClosure(static_cast<int>(device_count
),
498 base::Bind(&UsbServiceImpl::RefreshDevicesComplete
,
499 weak_factory_
.GetWeakPtr()));
500 std::list
<PlatformUsbDevice
> new_devices
;
502 // Look for new and existing devices.
503 for (size_t i
= 0; i
< device_count
; ++i
) {
504 PlatformUsbDevice platform_device
= platform_devices
[i
];
505 auto it
= platform_devices_
.find(platform_device
);
507 if (it
== platform_devices_
.end()) {
508 libusb_ref_device(platform_device
);
509 new_devices
.push_back(platform_device
);
511 it
->second
->set_visited(true);
512 refresh_complete
.Run();
516 // Remove devices not seen in this enumeration.
517 for (PlatformDeviceMap::iterator it
= platform_devices_
.begin();
518 it
!= platform_devices_
.end();
519 /* incremented internally */) {
520 PlatformDeviceMap::iterator current
= it
++;
521 const scoped_refptr
<UsbDeviceImpl
>& device
= current
->second
;
522 if (device
->was_visited()) {
523 device
->set_visited(false);
525 RemoveDevice(device
);
529 for (PlatformUsbDevice platform_device
: new_devices
) {
530 EnumerateDevice(platform_device
, refresh_complete
);
533 libusb_free_device_list(platform_devices
, true);
536 void UsbServiceImpl::RefreshDevicesComplete() {
537 DCHECK(CalledOnValidThread());
538 DCHECK(enumeration_in_progress_
);
540 enumeration_ready_
= true;
541 enumeration_in_progress_
= false;
542 devices_being_enumerated_
.clear();
544 if (!pending_enumeration_callbacks_
.empty()) {
545 std::vector
<scoped_refptr
<UsbDevice
>> devices
;
546 for (const auto& map_entry
: devices_
) {
547 devices
.push_back(map_entry
.second
);
550 std::vector
<GetDevicesCallback
> callbacks
;
551 callbacks
.swap(pending_enumeration_callbacks_
);
552 for (const GetDevicesCallback
& callback
: callbacks
) {
553 callback
.Run(devices
);
557 if (!pending_path_enumerations_
.empty()) {
562 void UsbServiceImpl::EnumerateDevice(PlatformUsbDevice platform_device
,
563 const base::Closure
& refresh_complete
) {
564 devices_being_enumerated_
.insert(platform_device
);
566 libusb_device_descriptor descriptor
;
567 int rv
= libusb_get_device_descriptor(platform_device
, &descriptor
);
568 if (rv
== LIBUSB_SUCCESS
) {
569 scoped_refptr
<UsbDeviceImpl
> device(
570 new UsbDeviceImpl(context_
, platform_device
, descriptor
.idVendor
,
571 descriptor
.idProduct
, blocking_task_runner_
));
573 base::Closure add_device
=
574 base::Bind(&UsbServiceImpl::AddDevice
, weak_factory_
.GetWeakPtr(),
575 refresh_complete
, device
);
577 #if defined(USE_UDEV)
578 blocking_task_runner_
->PostTask(
579 FROM_HERE
, base::Bind(&EnumerateUdevDevice
, device
, task_runner_
,
580 add_device
, refresh_complete
));
582 if (descriptor
.iManufacturer
== 0 && descriptor
.iProduct
== 0 &&
583 descriptor
.iSerialNumber
== 0) {
584 // Don't bother disturbing the device if it has no string descriptors to
588 device
->Open(base::Bind(&ReadDeviceLanguage
, descriptor
.iManufacturer
,
589 descriptor
.iProduct
, descriptor
.iSerialNumber
,
590 add_device
, refresh_complete
));
594 USB_LOG(EVENT
) << "Failed to get device descriptor: "
595 << ConvertPlatformUsbErrorToString(rv
);
596 refresh_complete
.Run();
600 void UsbServiceImpl::AddDevice(const base::Closure
& refresh_complete
,
601 scoped_refptr
<UsbDeviceImpl
> device
) {
602 auto it
= devices_being_enumerated_
.find(device
->platform_device());
603 if (it
== devices_being_enumerated_
.end()) {
604 // Device was removed while being enumerated.
605 refresh_complete
.Run();
609 platform_devices_
[device
->platform_device()] = device
;
610 DCHECK(!ContainsKey(devices_
, device
->guid()));
611 devices_
[device
->guid()] = device
;
613 USB_LOG(USER
) << "USB device added: vendor=" << device
->vendor_id() << " \""
614 << device
->manufacturer_string()
615 << "\", product=" << device
->product_id() << " \""
616 << device
->product_string() << "\", serial=\""
617 << device
->serial_number() << "\", guid=" << device
->guid();
619 if (enumeration_ready_
) {
620 NotifyDeviceAdded(device
);
623 refresh_complete
.Run();
626 void UsbServiceImpl::RemoveDevice(scoped_refptr
<UsbDeviceImpl
> device
) {
627 platform_devices_
.erase(device
->platform_device());
628 devices_
.erase(device
->guid());
630 USB_LOG(USER
) << "USB device removed: guid=" << device
->guid();
632 NotifyDeviceRemoved(device
);
633 device
->OnDisconnect();
637 int LIBUSB_CALL
UsbServiceImpl::HotplugCallback(libusb_context
* context
,
638 PlatformUsbDevice device
,
639 libusb_hotplug_event event
,
641 // It is safe to access the UsbServiceImpl* here because libusb takes a lock
642 // around registering, deregistering and calling hotplug callback functions
643 // and so guarantees that this function will not be called by the event
644 // processing thread after it has been deregistered.
645 UsbServiceImpl
* self
= reinterpret_cast<UsbServiceImpl
*>(user_data
);
647 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED
:
648 libusb_ref_device(device
); // Released in OnPlatformDeviceAdded.
649 if (self
->task_runner_
->BelongsToCurrentThread()) {
650 self
->OnPlatformDeviceAdded(device
);
652 self
->task_runner_
->PostTask(
653 FROM_HERE
, base::Bind(&UsbServiceImpl::OnPlatformDeviceAdded
,
654 base::Unretained(self
), device
));
657 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT
:
658 libusb_ref_device(device
); // Released in OnPlatformDeviceRemoved.
659 if (self
->task_runner_
->BelongsToCurrentThread()) {
660 self
->OnPlatformDeviceRemoved(device
);
662 self
->task_runner_
->PostTask(
663 FROM_HERE
, base::Bind(&UsbServiceImpl::OnPlatformDeviceRemoved
,
664 base::Unretained(self
), device
));
674 void UsbServiceImpl::OnPlatformDeviceAdded(PlatformUsbDevice platform_device
) {
675 DCHECK(CalledOnValidThread());
676 DCHECK(!ContainsKey(platform_devices_
, platform_device
));
677 EnumerateDevice(platform_device
, base::Bind(&base::DoNothing
));
678 libusb_unref_device(platform_device
);
681 void UsbServiceImpl::OnPlatformDeviceRemoved(
682 PlatformUsbDevice platform_device
) {
683 DCHECK(CalledOnValidThread());
684 PlatformDeviceMap::iterator it
= platform_devices_
.find(platform_device
);
685 if (it
!= platform_devices_
.end()) {
686 RemoveDevice(it
->second
);
688 DCHECK(ContainsKey(devices_being_enumerated_
, platform_device
));
689 devices_being_enumerated_
.erase(platform_device
);
691 libusb_unref_device(platform_device
);
694 } // namespace device