Index: chrome/browser/extensions/api/usb/usb_api.cc |
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc |
index 587fc7bdffe322a73835c8b79d487b04d0fb654f..d843f57f7329ac8ec7ec4699b8345cc3ea93fed7 100644 |
--- a/chrome/browser/extensions/api/usb/usb_api.cc |
+++ b/chrome/browser/extensions/api/usb/usb_api.cc |
@@ -18,6 +18,7 @@ |
namespace BulkTransfer = extensions::api::usb::BulkTransfer; |
namespace ClaimInterface = extensions::api::usb::ClaimInterface; |
+namespace ListInterfaces = extensions::api::usb::ListInterfaces; |
namespace CloseDevice = extensions::api::usb::CloseDevice; |
namespace ControlTransfer = extensions::api::usb::ControlTransfer; |
namespace FindDevices = extensions::api::usb::FindDevices; |
@@ -33,10 +34,15 @@ using std::vector; |
using usb::ControlTransferInfo; |
using usb::Device; |
using usb::Direction; |
+using usb::EndpointDescriptor; |
+using usb::EndpointType; |
using usb::GenericTransferInfo; |
+using usb::InterfaceDescriptor; |
using usb::IsochronousTransferInfo; |
using usb::Recipient; |
using usb::RequestType; |
+using usb::SynchronizationType; |
+using usb::UsageType; |
namespace { |
@@ -51,13 +57,18 @@ static const char* kErrorStalled = "Transfer stalled."; |
static const char* kErrorTimeout = "Transfer timed out."; |
static const char* kErrorTransferLength = "Transfer length is insufficient."; |
+static const char* kErrorCannotListInterfaces = "Error listing interfaces."; |
static const char* kErrorCannotClaimInterface = "Error claiming interface."; |
static const char* kErrorCannotReleaseInterface = "Error releasing interface."; |
static const char* kErrorCannotSetInterfaceAlternateSetting = |
"Error setting alternate interface setting."; |
static const char* kErrorConvertDirection = "Invalid transfer direction."; |
+static const char* kErrorConvertEndpointType = "Invalid endpoint type."; |
static const char* kErrorConvertRecipient = "Invalid transfer recipient."; |
static const char* kErrorConvertRequestType = "Invalid request type."; |
+static const char* kErrorConvertSynchronizationType = |
+ "Invalid synchronization type"; |
+static const char* kErrorConvertUsageType = "Invalid usage type."; |
static const char* kErrorMalformedParameters = "Error parsing parameters."; |
static const char* kErrorNoDevice = "No such device."; |
static const char* kErrorPermissionDenied = |
@@ -75,14 +86,95 @@ static const int kMaxPacketLength = 64 * 1024; |
static UsbDevice* device_for_test_ = NULL; |
+static bool ConvertDirectionToApi(const UsbInterfaceDirection& input, |
+ Direction* output) { |
+ switch (input) { |
+ case USB_DIRECTION_INBOUND: |
+ *output = usb::DIRECTION_IN; |
+ return true; |
+ case USB_DIRECTION_OUTBOUND: |
+ *output = usb::DIRECTION_OUT; |
+ return true; |
+ default: |
Bei Zhang
2013/04/26 22:38:01
I believe this should be:
default:
NOTREACHED()
Kenny Root (Google)
2013/05/08 01:15:08
Done.
|
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+static bool ConvertEndpointTypeToApi( |
+ const UsbEndpointType& input, |
+ extensions::api::usb::EndpointType* output) { |
+ switch (input) { |
+ case USB_ENDPOINT_CONTROL: |
+ *output = usb::ENDPOINT_TYPE_CONTROL; |
+ return true; |
+ case USB_ENDPOINT_INTERRUPT: |
+ *output = usb::ENDPOINT_TYPE_INTERRUPT; |
+ return true; |
+ case USB_ENDPOINT_ISOCHRONOUS: |
+ *output = usb::ENDPOINT_TYPE_ISOCHRONOUS; |
+ return true; |
+ case USB_ENDPOINT_BULK: |
+ *output = usb::ENDPOINT_TYPE_BULK; |
+ return true; |
+ default: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+static bool ConvertSynchronizationTypeToApi( |
+ const UsbSynchronizationType& input, |
+ extensions::api::usb::SynchronizationType* output) { |
+ switch (input) { |
+ case USB_SYNCHRONIZATION_NONE: |
+ *output = usb::SYNCHRONIZATION_TYPE_NONE; |
+ return true; |
+ case USB_SYNCHRONIZATION_ASYNCHRONOUS: |
+ *output = usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS; |
+ return true; |
+ case USB_SYNCHRONIZATION_ADAPTIVE: |
+ *output = usb::SYNCHRONIZATION_TYPE_ADAPTIVE; |
+ return true; |
+ case USB_SYNCHRONIZATION_SYNCHRONOUS: |
+ *output = usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS; |
+ return true; |
+ default: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+static bool ConvertUsageTypeToApi(const UsbUsageType& input, |
+ extensions::api::usb::UsageType* output) { |
+ switch (input) { |
+ case USB_USAGE_DATA: |
+ *output = usb::USAGE_TYPE_DATA; |
+ return true; |
+ case USB_USAGE_FEEDBACK: |
+ *output = usb::USAGE_TYPE_FEEDBACK; |
+ return true; |
+ case USB_USAGE_EXPLICIT_FEEDBACK: |
+ *output = usb::USAGE_TYPE_EXPLICITFEEDBACK; |
+ return true; |
+ default: |
+ return false; |
+ } |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
static bool ConvertDirection(const Direction& input, |
- UsbDevice::TransferDirection* output) { |
+ UsbInterfaceDirection* output) { |
switch (input) { |
case usb::DIRECTION_IN: |
- *output = UsbDevice::INBOUND; |
+ *output = USB_DIRECTION_INBOUND; |
return true; |
case usb::DIRECTION_OUT: |
- *output = UsbDevice::OUTBOUND; |
+ *output = USB_DIRECTION_OUTBOUND; |
return true; |
default: |
return false; |
@@ -155,7 +247,7 @@ static bool GetTransferSize(const T& input, size_t* output) { |
template<class T> |
static scoped_refptr<net::IOBuffer> CreateBufferForTransfer( |
- const T& input, UsbDevice::TransferDirection direction, size_t size) { |
+ const T& input, UsbInterfaceDirection direction, size_t size) { |
if (size >= kMaxTransferLength) |
return NULL; |
@@ -166,9 +258,9 @@ static scoped_refptr<net::IOBuffer> CreateBufferForTransfer( |
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(std::max( |
static_cast<size_t>(1), size)); |
- if (direction == UsbDevice::INBOUND) { |
+ if (direction == USB_DIRECTION_INBOUND) { |
return buffer; |
- } else if (direction == UsbDevice::OUTBOUND) { |
+ } else if (direction == USB_DIRECTION_OUTBOUND) { |
if (input.data.get() && size <= input.data->size()) { |
memcpy(buffer->data(), input.data->data(), size); |
return buffer; |
@@ -222,6 +314,20 @@ static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) { |
return device.ToValue().release(); |
} |
+static base::Value* PopulateInterfaceDescriptor(int interface_number, |
+ int alternate_setting, int interface_class, int interface_subclass, |
+ int interface_protocol, |
+ std::vector<linked_ptr<EndpointDescriptor> >* endpoints) { |
+ InterfaceDescriptor descriptor; |
+ descriptor.interface_number = interface_number; |
+ descriptor.alternate_setting = alternate_setting; |
+ descriptor.interface_class = interface_class; |
+ descriptor.interface_subclass = interface_subclass; |
+ descriptor.interface_protocol = interface_subclass; |
+ descriptor.endpoints = *endpoints; |
+ return descriptor.ToValue().release(); |
+} |
+ |
} // namespace |
namespace extensions { |
@@ -271,7 +377,7 @@ void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status, |
} |
bool UsbAsyncApiTransferFunction::ConvertDirectionSafely( |
- const Direction& input, UsbDevice::TransferDirection* output) { |
+ const Direction& input, UsbInterfaceDirection* output) { |
const bool converted = ConvertDirection(input, output); |
if (!converted) |
SetError(kErrorConvertDirection); |
@@ -361,6 +467,133 @@ void UsbFindDevicesFunction::OnCompleted() { |
AsyncWorkCompleted(); |
} |
+UsbListInterfacesFunction::UsbListInterfacesFunction() {} |
+ |
+UsbListInterfacesFunction::~UsbListInterfacesFunction() {} |
+ |
+bool UsbListInterfacesFunction::Prepare() { |
+ parameters_ = ListInterfaces::Params::Create(*args_); |
+ EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
+ return true; |
+} |
+ |
+void UsbListInterfacesFunction::AsyncWorkStart() { |
+ UsbDeviceResource* const device = GetUsbDeviceResource( |
+ parameters_->device.handle); |
+ if (!device) { |
+ CompleteWithError(kErrorNoDevice); |
+ return; |
+ } |
+ |
+ PlatformUsbConfigDescriptor platform_config = NULL; |
+ |
+ device->device()->ListInterfaces(&platform_config, base::Bind( |
+ &UsbListInterfacesFunction::OnCompleted, this)); |
+ |
+ config_ = new UsbConfigDescriptor(platform_config); |
Bei Zhang
2013/04/26 22:38:01
Can you put some comment to explain these two line
Kenny Root (Google)
2013/05/08 01:15:08
Oh, I see your point. This doesn't actually work.
|
+ |
+ RemoveUsbDeviceResource(parameters_->device.handle); |
+} |
+ |
+void UsbListInterfacesFunction::OnCompleted(bool success) { |
+ if (!success) { |
+ SetError(kErrorCannotListInterfaces); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ for (size_t i = 0, numInterfaces = config_->numInterfaces(); |
Kenny Root (Google)
2013/05/08 01:15:08
I might be able to move this all into AsyncWorkSta
|
+ i < numInterfaces; ++i) { |
+ scoped_refptr<const UsbInterface> usbInterface(config_->getInterface(i)); |
+ for (size_t j = 0, numDescriptors = usbInterface->numAltSettings(); |
+ i < numDescriptors; ++i) { |
+ scoped_refptr<const UsbInterfaceDescriptor> descriptor |
+ = usbInterface->getAltSetting(j); |
+ std::vector<linked_ptr<EndpointDescriptor> > endpoints; |
+ for (size_t k = 0, numEndpoints = descriptor->numEndpoints(); |
+ k < numEndpoints; k++) { |
+ scoped_refptr<const UsbEndpointDescriptor> endpoint |
+ = descriptor->getEndpoint(k); |
+ linked_ptr<EndpointDescriptor> endpoint_desc(new EndpointDescriptor()); |
+ |
+ EndpointType type; |
+ Direction direction; |
+ SynchronizationType synchronization; |
+ UsageType usage; |
+ |
+ if (!ConvertEndpointTypeSafely(endpoint->GetEndpointType(), &type) || |
+ !ConvertDirectionSafely(endpoint->GetDirection(), &direction) || |
+ !ConvertSynchronizationTypeSafely( |
+ endpoint->GetSynchronizationType(), &synchronization) || |
+ !ConvertUsageTypeSafely(endpoint->GetUsageType(), &usage)) { |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ endpoint_desc->address = endpoint->GetAddress(); |
+ endpoint_desc->type = type; |
+ endpoint_desc->direction = direction; |
+ endpoint_desc->maximum_packet_size = endpoint->GetMaximumPacketSize(); |
+ endpoint_desc->synchronization = synchronization; |
+ endpoint_desc->usage = usage; |
+ |
+ int* polling_interval = new int; |
+ endpoint_desc->polling_interval.reset(polling_interval); |
+ *polling_interval = endpoint->GetPollingInterval(); |
+ |
+ endpoints.push_back(endpoint_desc); |
+ } |
+ |
+ result_->Append(PopulateInterfaceDescriptor( |
+ descriptor->GetInterfaceNumber(), |
+ descriptor->GetAlternateSetting(), |
+ descriptor->GetInterfaceClass(), |
+ descriptor->GetInterfaceSubclass(), |
+ descriptor->GetInterfaceProtocol(), |
+ &endpoints)); |
+ } |
+ } |
+ |
+ SetResult(result_.release()); |
+ AsyncWorkCompleted(); |
+} |
+ |
+bool UsbListInterfacesFunction::ConvertDirectionSafely( |
+ const UsbInterfaceDirection& input, |
+ extensions::api::usb::Direction* output) { |
+ const bool converted = ConvertDirectionToApi(input, output); |
+ if (!converted) |
+ SetError(kErrorConvertDirection); |
+ return converted; |
+} |
+ |
+bool UsbListInterfacesFunction::ConvertEndpointTypeSafely( |
+ const UsbEndpointType& input, |
+ extensions::api::usb::EndpointType* output) { |
+ const bool converted = ConvertEndpointTypeToApi(input, output); |
+ if (!converted) |
+ SetError(kErrorConvertEndpointType); |
+ return converted; |
+} |
+ |
+bool UsbListInterfacesFunction::ConvertSynchronizationTypeSafely( |
+ const UsbSynchronizationType& input, |
+ extensions::api::usb::SynchronizationType* output) { |
+ const bool converted = ConvertSynchronizationTypeToApi(input, output); |
+ if (!converted) |
+ SetError(kErrorConvertSynchronizationType); |
+ return converted; |
+} |
+ |
+bool UsbListInterfacesFunction::ConvertUsageTypeSafely( |
+ const UsbUsageType& input, |
+ extensions::api::usb::UsageType* output) { |
+ const bool converted = ConvertUsageTypeToApi(input, output); |
+ if (!converted) |
+ SetError(kErrorConvertUsageType); |
+ return converted; |
+} |
+ |
UsbCloseDeviceFunction::UsbCloseDeviceFunction() {} |
UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {} |
@@ -493,7 +726,7 @@ void UsbControlTransferFunction::AsyncWorkStart() { |
const ControlTransferInfo& transfer = parameters_->transfer_info; |
- UsbDevice::TransferDirection direction; |
+ UsbInterfaceDirection direction; |
UsbDevice::TransferRequestType request_type; |
UsbDevice::TransferRecipient recipient; |
size_t size = 0; |
@@ -542,7 +775,7 @@ void UsbBulkTransferFunction::AsyncWorkStart() { |
const GenericTransferInfo& transfer = parameters_->transfer_info; |
- UsbDevice::TransferDirection direction; |
+ UsbInterfaceDirection direction; |
size_t size = 0; |
if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
@@ -586,7 +819,7 @@ void UsbInterruptTransferFunction::AsyncWorkStart() { |
const GenericTransferInfo& transfer = parameters_->transfer_info; |
- UsbDevice::TransferDirection direction; |
+ UsbInterfaceDirection direction; |
size_t size = 0; |
if (!ConvertDirectionSafely(transfer.direction, &direction)) { |
@@ -632,7 +865,7 @@ void UsbIsochronousTransferFunction::AsyncWorkStart() { |
const GenericTransferInfo& generic_transfer = transfer.transfer_info; |
size_t size = 0; |
- UsbDevice::TransferDirection direction; |
+ UsbInterfaceDirection direction; |
if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { |
AsyncWorkCompleted(); |