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_device_impl.h"
10 #include "base/location.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/stl_util.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "components/device_event_log/device_event_log.h"
17 #include "device/usb/usb_context.h"
18 #include "device/usb/usb_descriptors.h"
19 #include "device/usb/usb_device_handle_impl.h"
20 #include "device/usb/usb_error.h"
21 #include "third_party/libusb/src/libusb/libusb.h"
23 #if defined(OS_CHROMEOS)
24 #include "base/sys_info.h"
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/dbus/permission_broker_client.h"
27 #endif // defined(OS_CHROMEOS)
30 #include "device/udev_linux/scoped_udev.h"
31 #endif // defined(USE_UDEV)
37 #if defined(OS_CHROMEOS)
38 void OnRequestUsbAccessReplied(
39 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
,
40 const base::Callback
<void(bool success
)>& callback
,
42 task_runner
->PostTask(FROM_HERE
, base::Bind(callback
, success
));
44 #endif // defined(OS_CHROMEOS)
46 UsbEndpointDirection
GetDirection(
47 const libusb_endpoint_descriptor
* descriptor
) {
48 switch (descriptor
->bEndpointAddress
& LIBUSB_ENDPOINT_DIR_MASK
) {
49 case LIBUSB_ENDPOINT_IN
:
50 return USB_DIRECTION_INBOUND
;
51 case LIBUSB_ENDPOINT_OUT
:
52 return USB_DIRECTION_OUTBOUND
;
55 return USB_DIRECTION_INBOUND
;
59 UsbSynchronizationType
GetSynchronizationType(
60 const libusb_endpoint_descriptor
* descriptor
) {
61 switch ((descriptor
->bmAttributes
& LIBUSB_ISO_SYNC_TYPE_MASK
) >> 2) {
62 case LIBUSB_ISO_SYNC_TYPE_NONE
:
63 return USB_SYNCHRONIZATION_NONE
;
64 case LIBUSB_ISO_SYNC_TYPE_ASYNC
:
65 return USB_SYNCHRONIZATION_ASYNCHRONOUS
;
66 case LIBUSB_ISO_SYNC_TYPE_ADAPTIVE
:
67 return USB_SYNCHRONIZATION_ADAPTIVE
;
68 case LIBUSB_ISO_SYNC_TYPE_SYNC
:
69 return USB_SYNCHRONIZATION_SYNCHRONOUS
;
72 return USB_SYNCHRONIZATION_NONE
;
76 UsbTransferType
GetTransferType(const libusb_endpoint_descriptor
* descriptor
) {
77 switch (descriptor
->bmAttributes
& LIBUSB_TRANSFER_TYPE_MASK
) {
78 case LIBUSB_TRANSFER_TYPE_CONTROL
:
79 return USB_TRANSFER_CONTROL
;
80 case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS
:
81 return USB_TRANSFER_ISOCHRONOUS
;
82 case LIBUSB_TRANSFER_TYPE_BULK
:
83 return USB_TRANSFER_BULK
;
84 case LIBUSB_TRANSFER_TYPE_INTERRUPT
:
85 return USB_TRANSFER_INTERRUPT
;
88 return USB_TRANSFER_CONTROL
;
92 UsbUsageType
GetUsageType(const libusb_endpoint_descriptor
* descriptor
) {
93 switch ((descriptor
->bmAttributes
& LIBUSB_ISO_USAGE_TYPE_MASK
) >> 4) {
94 case LIBUSB_ISO_USAGE_TYPE_DATA
:
95 return USB_USAGE_DATA
;
96 case LIBUSB_ISO_USAGE_TYPE_FEEDBACK
:
97 return USB_USAGE_FEEDBACK
;
98 case LIBUSB_ISO_USAGE_TYPE_IMPLICIT
:
99 return USB_USAGE_EXPLICIT_FEEDBACK
;
102 return USB_USAGE_DATA
;
108 UsbDeviceImpl::UsbDeviceImpl(
109 scoped_refptr
<UsbContext
> context
,
110 scoped_refptr
<base::SingleThreadTaskRunner
> ui_task_runner
,
111 PlatformUsbDevice platform_device
,
115 : UsbDevice(vendor_id
, product_id
, unique_id
),
116 platform_device_(platform_device
),
118 ui_task_runner_(ui_task_runner
) {
119 CHECK(platform_device
) << "platform_device cannot be NULL";
120 libusb_ref_device(platform_device
);
121 RefreshConfiguration();
122 #if defined(USE_UDEV)
123 ScopedUdevPtr
udev(udev_new());
124 ScopedUdevEnumeratePtr
enumerate(udev_enumerate_new(udev
.get()));
126 udev_enumerate_add_match_subsystem(enumerate
.get(), "usb");
127 if (udev_enumerate_scan_devices(enumerate
.get()) != 0) {
130 std::string bus_number
=
131 base::IntToString(libusb_get_bus_number(platform_device
));
132 std::string device_address
=
133 base::IntToString(libusb_get_device_address(platform_device
));
134 udev_list_entry
* devices
= udev_enumerate_get_list_entry(enumerate
.get());
135 for (udev_list_entry
* i
= devices
; i
!= NULL
;
136 i
= udev_list_entry_get_next(i
)) {
137 ScopedUdevDevicePtr
device(
138 udev_device_new_from_syspath(udev
.get(), udev_list_entry_get_name(i
)));
140 const char* value
= udev_device_get_sysattr_value(device
.get(), "busnum");
141 if (!value
|| bus_number
!= value
) {
144 value
= udev_device_get_sysattr_value(device
.get(), "devnum");
145 if (!value
|| device_address
!= value
) {
149 #if defined(OS_CHROMEOS)
150 value
= udev_device_get_devnode(device
.get());
155 value
= udev_device_get_sysattr_value(device
.get(), "manufacturer");
157 manufacturer_
= base::UTF8ToUTF16(value
);
159 value
= udev_device_get_sysattr_value(device
.get(), "product");
161 product_
= base::UTF8ToUTF16(value
);
163 value
= udev_device_get_sysattr_value(device
.get(), "serial");
165 serial_number_
= base::UTF8ToUTF16(value
);
171 strings_cached_
= false;
175 UsbDeviceImpl::~UsbDeviceImpl() {
176 // The destructor must be safe to call from any thread.
177 libusb_unref_device(platform_device_
);
180 #if defined(OS_CHROMEOS)
182 void UsbDeviceImpl::RequestUsbAccess(
184 const base::Callback
<void(bool success
)>& callback
) {
185 DCHECK(thread_checker_
.CalledOnValidThread());
187 // ChromeOS builds on non-ChromeOS machines (dev) should not attempt to
188 // use permission broker.
189 if (base::SysInfo::IsRunningOnChromeOS()) {
190 chromeos::PermissionBrokerClient
* client
=
191 chromeos::DBusThreadManager::Get()->GetPermissionBrokerClient();
192 DCHECK(client
) << "Could not get permission broker client.";
198 ui_task_runner_
->PostTask(
200 base::Bind(&chromeos::PermissionBrokerClient::RequestPathAccess
,
201 base::Unretained(client
),
204 base::Bind(&OnRequestUsbAccessReplied
,
205 base::ThreadTaskRunnerHandle::Get(),
208 // Not really running on Chrome OS, declare success.
215 scoped_refptr
<UsbDeviceHandle
> UsbDeviceImpl::Open() {
216 DCHECK(thread_checker_
.CalledOnValidThread());
217 PlatformUsbDeviceHandle handle
;
218 const int rv
= libusb_open(platform_device_
, &handle
);
219 if (LIBUSB_SUCCESS
== rv
) {
220 scoped_refptr
<UsbDeviceHandleImpl
> device_handle
=
221 new UsbDeviceHandleImpl(context_
, this, handle
);
222 handles_
.push_back(device_handle
);
223 return device_handle
;
225 USB_LOG(EVENT
) << "Failed to open device: "
226 << ConvertPlatformUsbErrorToString(rv
);
231 bool UsbDeviceImpl::Close(scoped_refptr
<UsbDeviceHandle
> handle
) {
232 DCHECK(thread_checker_
.CalledOnValidThread());
234 for (HandlesVector::iterator it
= handles_
.begin(); it
!= handles_
.end();
236 if (it
->get() == handle
.get()) {
237 (*it
)->InternalClose();
245 const UsbConfigDescriptor
* UsbDeviceImpl::GetConfiguration() {
246 DCHECK(thread_checker_
.CalledOnValidThread());
247 return configuration_
.get();
250 bool UsbDeviceImpl::GetManufacturer(base::string16
* manufacturer
) {
251 DCHECK(thread_checker_
.CalledOnValidThread());
253 #if !defined(USE_UDEV)
254 if (!strings_cached_
) {
259 *manufacturer
= manufacturer_
;
260 return !manufacturer_
.empty();
263 bool UsbDeviceImpl::GetProduct(base::string16
* product
) {
264 DCHECK(thread_checker_
.CalledOnValidThread());
266 #if !defined(USE_UDEV)
267 if (!strings_cached_
) {
273 return !product_
.empty();
276 bool UsbDeviceImpl::GetSerialNumber(base::string16
* serial_number
) {
277 DCHECK(thread_checker_
.CalledOnValidThread());
279 #if !defined(USE_UDEV)
280 if (!strings_cached_
) {
285 *serial_number
= serial_number_
;
286 return !serial_number_
.empty();
289 void UsbDeviceImpl::OnDisconnect() {
290 DCHECK(thread_checker_
.CalledOnValidThread());
292 // Swap the list of handles into a local variable because closing all open
293 // handles may release the last reference to this object.
294 HandlesVector handles
;
295 swap(handles
, handles_
);
297 for (const scoped_refptr
<UsbDeviceHandleImpl
>& handle
: handles_
) {
298 handle
->InternalClose();
302 void UsbDeviceImpl::RefreshConfiguration() {
303 libusb_config_descriptor
* platform_config
;
305 libusb_get_active_config_descriptor(platform_device_
, &platform_config
);
306 if (rv
!= LIBUSB_SUCCESS
) {
307 USB_LOG(EVENT
) << "Failed to get config descriptor: "
308 << ConvertPlatformUsbErrorToString(rv
);
312 configuration_
.reset(new UsbConfigDescriptor());
313 configuration_
->configuration_value
= platform_config
->bConfigurationValue
;
314 configuration_
->self_powered
= (platform_config
->bmAttributes
& 0x40) != 0;
315 configuration_
->remote_wakeup
= (platform_config
->bmAttributes
& 0x20) != 0;
316 configuration_
->maximum_power
= platform_config
->MaxPower
* 2;
318 for (size_t i
= 0; i
< platform_config
->bNumInterfaces
; ++i
) {
319 const struct libusb_interface
* platform_interface
=
320 &platform_config
->interface
[i
];
321 for (int j
= 0; j
< platform_interface
->num_altsetting
; ++j
) {
322 const struct libusb_interface_descriptor
* platform_alt_setting
=
323 &platform_interface
->altsetting
[j
];
324 UsbInterfaceDescriptor interface
;
326 interface
.interface_number
= platform_alt_setting
->bInterfaceNumber
;
327 interface
.alternate_setting
= platform_alt_setting
->bAlternateSetting
;
328 interface
.interface_class
= platform_alt_setting
->bInterfaceClass
;
329 interface
.interface_subclass
= platform_alt_setting
->bInterfaceSubClass
;
330 interface
.interface_protocol
= platform_alt_setting
->bInterfaceProtocol
;
332 for (size_t k
= 0; k
< platform_alt_setting
->bNumEndpoints
; ++k
) {
333 const struct libusb_endpoint_descriptor
* platform_endpoint
=
334 &platform_alt_setting
->endpoint
[k
];
335 UsbEndpointDescriptor endpoint
;
337 endpoint
.address
= platform_endpoint
->bEndpointAddress
;
338 endpoint
.direction
= GetDirection(platform_endpoint
);
339 endpoint
.maximum_packet_size
= platform_endpoint
->wMaxPacketSize
;
340 endpoint
.synchronization_type
=
341 GetSynchronizationType(platform_endpoint
);
342 endpoint
.transfer_type
= GetTransferType(platform_endpoint
);
343 endpoint
.usage_type
= GetUsageType(platform_endpoint
);
344 endpoint
.polling_interval
= platform_endpoint
->bInterval
;
345 endpoint
.extra_data
= std::vector
<uint8_t>(
346 platform_endpoint
->extra
,
347 platform_endpoint
->extra
+ platform_endpoint
->extra_length
);
349 interface
.endpoints
.push_back(endpoint
);
352 interface
.extra_data
= std::vector
<uint8_t>(
353 platform_alt_setting
->extra
,
354 platform_alt_setting
->extra
+ platform_alt_setting
->extra_length
);
356 configuration_
->interfaces
.push_back(interface
);
360 configuration_
->extra_data
= std::vector
<uint8_t>(
361 platform_config
->extra
,
362 platform_config
->extra
+ platform_config
->extra_length
);
364 libusb_free_config_descriptor(platform_config
);
367 #if !defined(USE_UDEV)
368 void UsbDeviceImpl::CacheStrings() {
369 DCHECK(thread_checker_
.CalledOnValidThread());
370 // This is a non-blocking call as libusb has the descriptor in memory.
371 libusb_device_descriptor desc
;
372 const int rv
= libusb_get_device_descriptor(platform_device_
, &desc
);
373 if (rv
== LIBUSB_SUCCESS
) {
374 scoped_refptr
<UsbDeviceHandle
> device_handle
= Open();
375 if (device_handle
.get()) {
376 if (desc
.iManufacturer
!= 0) {
377 device_handle
->GetStringDescriptor(desc
.iManufacturer
, &manufacturer_
);
379 if (desc
.iProduct
!= 0) {
380 device_handle
->GetStringDescriptor(desc
.iProduct
, &product_
);
382 if (desc
.iSerialNumber
!= 0) {
383 device_handle
->GetStringDescriptor(desc
.iSerialNumber
, &serial_number_
);
385 device_handle
->Close();
387 USB_LOG(EVENT
) << "Failed to open device to cache string descriptors.";
391 << "Failed to read device descriptor to cache string descriptors: "
392 << ConvertPlatformUsbErrorToString(rv
);
394 strings_cached_
= true;
396 #endif // !defined(USE_UDEV)
398 } // namespace device