Index: device/usb/usb_device_impl.cc |
diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc |
index 03c8ee0b8d74843dd65828c01c0d209d5b957a92..d0dc78097e9b916e4a64b96eda986c7b359b5832 100644 |
--- a/device/usb/usb_device_impl.cc |
+++ b/device/usb/usb_device_impl.cc |
@@ -12,9 +12,9 @@ |
#include "base/stl_util.h" |
#include "base/thread_task_runner_handle.h" |
#include "device/usb/usb_context.h" |
+#include "device/usb/usb_descriptors.h" |
#include "device/usb/usb_device_handle_impl.h" |
#include "device/usb/usb_error.h" |
-#include "device/usb/usb_interface_impl.h" |
#include "third_party/libusb/src/libusb/libusb.h" |
#if defined(OS_CHROMEOS) |
@@ -23,6 +23,8 @@ |
#include "chromeos/dbus/permission_broker_client.h" |
#endif // defined(OS_CHROMEOS) |
+namespace device { |
+ |
namespace { |
#if defined(OS_CHROMEOS) |
@@ -34,9 +36,67 @@ void OnRequestUsbAccessReplied( |
} |
#endif // defined(OS_CHROMEOS) |
-} // namespace |
+UsbEndpointDirection GetDirection( |
+ const libusb_endpoint_descriptor* descriptor) { |
+ switch (descriptor->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) { |
+ case LIBUSB_ENDPOINT_IN: |
+ return USB_DIRECTION_INBOUND; |
+ case LIBUSB_ENDPOINT_OUT: |
+ return USB_DIRECTION_OUTBOUND; |
+ default: |
+ NOTREACHED(); |
+ return USB_DIRECTION_INBOUND; |
+ } |
+} |
-namespace device { |
+UsbSynchronizationType GetSynchronizationType( |
+ const libusb_endpoint_descriptor* descriptor) { |
+ switch (descriptor->bmAttributes & LIBUSB_ISO_SYNC_TYPE_MASK) { |
+ case LIBUSB_ISO_SYNC_TYPE_NONE: |
+ return USB_SYNCHRONIZATION_NONE; |
+ case LIBUSB_ISO_SYNC_TYPE_ASYNC: |
+ return USB_SYNCHRONIZATION_ASYNCHRONOUS; |
+ case LIBUSB_ISO_SYNC_TYPE_ADAPTIVE: |
+ return USB_SYNCHRONIZATION_ADAPTIVE; |
+ case LIBUSB_ISO_SYNC_TYPE_SYNC: |
+ return USB_SYNCHRONIZATION_SYNCHRONOUS; |
+ default: |
+ NOTREACHED(); |
+ return USB_SYNCHRONIZATION_NONE; |
+ } |
+} |
+ |
+UsbTransferType GetTransferType(const libusb_endpoint_descriptor* descriptor) { |
+ switch (descriptor->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) { |
+ case LIBUSB_TRANSFER_TYPE_CONTROL: |
+ return USB_TRANSFER_CONTROL; |
+ case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: |
+ return USB_TRANSFER_ISOCHRONOUS; |
+ case LIBUSB_TRANSFER_TYPE_BULK: |
+ return USB_TRANSFER_BULK; |
+ case LIBUSB_TRANSFER_TYPE_INTERRUPT: |
+ return USB_TRANSFER_INTERRUPT; |
+ default: |
+ NOTREACHED(); |
+ return USB_TRANSFER_CONTROL; |
+ } |
+} |
+ |
+UsbUsageType GetUsageType(const libusb_endpoint_descriptor* descriptor) { |
+ switch (descriptor->bmAttributes & LIBUSB_ISO_USAGE_TYPE_MASK) { |
+ case LIBUSB_ISO_USAGE_TYPE_DATA: |
+ return USB_USAGE_DATA; |
+ case LIBUSB_ISO_USAGE_TYPE_FEEDBACK: |
+ return USB_USAGE_FEEDBACK; |
+ case LIBUSB_ISO_USAGE_TYPE_IMPLICIT: |
+ return USB_USAGE_EXPLICIT_FEEDBACK; |
+ default: |
+ NOTREACHED(); |
+ return USB_USAGE_DATA; |
+ } |
+} |
+ |
+} // namespace |
UsbDeviceImpl::UsbDeviceImpl( |
scoped_refptr<UsbContext> context, |
@@ -47,6 +107,7 @@ UsbDeviceImpl::UsbDeviceImpl( |
uint32 unique_id) |
: UsbDevice(vendor_id, product_id, unique_id), |
platform_device_(platform_device), |
+ current_configuration_cached_(false), |
context_(context), |
ui_task_runner_(ui_task_runner) { |
CHECK(platform_device) << "platform_device cannot be NULL"; |
@@ -101,11 +162,12 @@ scoped_refptr<UsbDeviceHandle> UsbDeviceImpl::Open() { |
PlatformUsbDeviceHandle handle; |
const int rv = libusb_open(platform_device_, &handle); |
if (LIBUSB_SUCCESS == rv) { |
- scoped_refptr<UsbConfigDescriptor> interfaces = ListInterfaces(); |
- if (!interfaces.get()) |
+ GetConfiguration(); |
+ if (!current_configuration_cached_) { |
return NULL; |
+ } |
scoped_refptr<UsbDeviceHandleImpl> device_handle = |
- new UsbDeviceHandleImpl(context_, this, handle, interfaces); |
+ new UsbDeviceHandleImpl(context_, this, handle, current_configuration_); |
handles_.push_back(device_handle); |
return device_handle; |
} else { |
@@ -128,19 +190,76 @@ bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { |
return false; |
} |
-scoped_refptr<UsbConfigDescriptor> UsbDeviceImpl::ListInterfaces() { |
+const UsbConfigDescriptor& UsbDeviceImpl::GetConfiguration() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- PlatformUsbConfigDescriptor platform_config; |
- const int rv = |
- libusb_get_active_config_descriptor(platform_device_, &platform_config); |
- if (rv == LIBUSB_SUCCESS) { |
- return new UsbConfigDescriptorImpl(platform_config); |
- } else { |
- VLOG(1) << "Failed to get config descriptor: " |
- << ConvertPlatformUsbErrorToString(rv); |
- return NULL; |
+ if (!current_configuration_cached_) { |
+ libusb_config_descriptor* platform_config; |
+ const int rv = |
+ libusb_get_active_config_descriptor(platform_device_, &platform_config); |
+ if (rv != LIBUSB_SUCCESS) { |
+ VLOG(1) << "Failed to get config descriptor: " |
+ << ConvertPlatformUsbErrorToString(rv); |
+ return current_configuration_; |
+ } |
+ |
+ current_configuration_.configuration_value = |
+ platform_config->bConfigurationValue; |
+ current_configuration_.self_powered = |
+ (platform_config->bmAttributes & 0x40) != 0; |
+ current_configuration_.remote_wakeup = |
+ (platform_config->bmAttributes & 0x20) != 0; |
+ current_configuration_.maximum_power = platform_config->MaxPower * 2; |
+ |
+ for (size_t i = 0; i < platform_config->bNumInterfaces; ++i) { |
+ const struct libusb_interface* platform_interface = |
+ &platform_config->interface[i]; |
+ for (int j = 0; j < platform_interface->num_altsetting; ++j) { |
+ const struct libusb_interface_descriptor* platform_alt_setting = |
+ &platform_interface->altsetting[j]; |
+ UsbInterfaceDescriptor interface; |
+ |
+ interface.interface_number = platform_alt_setting->bInterfaceNumber; |
+ interface.alternate_setting = platform_alt_setting->bAlternateSetting; |
+ interface.interface_class = platform_alt_setting->bInterfaceClass; |
+ interface.interface_subclass = platform_alt_setting->bInterfaceSubClass; |
+ interface.interface_protocol = platform_alt_setting->bInterfaceProtocol; |
+ |
+ for (size_t k = 0; k < platform_alt_setting->bNumEndpoints; ++k) { |
+ const struct libusb_endpoint_descriptor* platform_endpoint = |
+ &platform_alt_setting->endpoint[k]; |
+ UsbEndpointDescriptor endpoint; |
+ |
+ endpoint.address = platform_endpoint->bEndpointAddress; |
+ endpoint.direction = GetDirection(platform_endpoint); |
+ endpoint.maximum_packet_size = platform_endpoint->wMaxPacketSize; |
+ endpoint.synchronization_type = |
+ GetSynchronizationType(platform_endpoint); |
+ endpoint.transfer_type = GetTransferType(platform_endpoint); |
+ endpoint.usage_type = GetUsageType(platform_endpoint); |
+ endpoint.polling_interval = platform_endpoint->bInterval; |
+ endpoint.extra_data = std::vector<uint8_t>( |
+ platform_endpoint->extra, |
+ platform_endpoint->extra + platform_endpoint->extra_length); |
+ |
+ interface.endpoints.push_back(endpoint); |
+ } |
+ |
+ interface.extra_data = std::vector<uint8_t>( |
+ platform_alt_setting->extra, |
+ platform_alt_setting->extra + platform_alt_setting->extra_length); |
+ |
+ current_configuration_.interfaces.push_back(interface); |
+ } |
+ } |
+ |
+ current_configuration_.extra_data = std::vector<uint8_t>( |
+ platform_config->extra, |
+ platform_config->extra + platform_config->extra_length); |
+ current_configuration_cached_ = true; |
} |
+ |
+ return current_configuration_; |
} |
void UsbDeviceImpl::OnDisconnect() { |