Chromium Code Reviews| 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(); |