OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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. |
| 4 |
| 5 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" |
| 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" |
| 12 #include "base/synchronization/lock.h" |
| 13 #include "chrome/browser/extensions/api/api_resource_event_notifier.h" |
| 14 #include "chrome/browser/extensions/api/api_resource.h" |
| 15 #include "chrome/browser/usb/usb_device.h" |
| 16 #include "chrome/common/extensions/api/experimental.usb.h" |
| 17 |
| 18 using extensions::api::experimental_usb::ControlTransferInfo; |
| 19 using extensions::api::experimental_usb::GenericTransferInfo; |
| 20 using std::string; |
| 21 using std::vector; |
| 22 |
| 23 static const char* kDirectionIn = "in"; |
| 24 static const char* kDirectionOut = "out"; |
| 25 |
| 26 static const char* kRequestTypeStandard = "standard"; |
| 27 static const char* kRequestTypeClass = "class"; |
| 28 static const char* kRequestTypeVendor = "vendor"; |
| 29 static const char* kRequestTypeReserved = "reserved"; |
| 30 |
| 31 static const char* kRecipientDevice = "device"; |
| 32 static const char* kRecipientInterface = "interface"; |
| 33 static const char* kRecipientEndpoint = "endpoint"; |
| 34 static const char* kRecipientOther = "other"; |
| 35 |
| 36 namespace { |
| 37 |
| 38 static bool ConvertDirection(const string& input, |
| 39 UsbDevice::TransferDirection* output) { |
| 40 if (input == kDirectionIn) { |
| 41 *output = UsbDevice::INBOUND; |
| 42 return true; |
| 43 } else if (input == kDirectionOut) { |
| 44 *output = UsbDevice::OUTBOUND; |
| 45 return true; |
| 46 } |
| 47 return false; |
| 48 } |
| 49 |
| 50 static bool ConvertRequestType(const string& input, |
| 51 UsbDevice::TransferRequestType* output) { |
| 52 if (input == kRequestTypeStandard) { |
| 53 *output = UsbDevice::STANDARD; |
| 54 return true; |
| 55 } else if (input == kRequestTypeClass) { |
| 56 *output = UsbDevice::CLASS; |
| 57 return true; |
| 58 } else if (input == kRequestTypeVendor) { |
| 59 *output = UsbDevice::VENDOR; |
| 60 return true; |
| 61 } else if (input == kRequestTypeReserved) { |
| 62 *output = UsbDevice::RESERVED; |
| 63 return true; |
| 64 } |
| 65 return false; |
| 66 } |
| 67 |
| 68 static bool ConvertRecipient(const string& input, |
| 69 UsbDevice::TransferRecipient* output) { |
| 70 if (input == kRecipientDevice) { |
| 71 *output = UsbDevice::DEVICE; |
| 72 return true; |
| 73 } else if (input == kRecipientInterface) { |
| 74 *output = UsbDevice::INTERFACE; |
| 75 return true; |
| 76 } else if (input == kRecipientEndpoint) { |
| 77 *output = UsbDevice::ENDPOINT; |
| 78 return true; |
| 79 } else if (input == kRecipientOther) { |
| 80 *output = UsbDevice::OTHER; |
| 81 return true; |
| 82 } |
| 83 return false; |
| 84 } |
| 85 |
| 86 template<class T> |
| 87 static bool GetTransferSize(const T& input, unsigned int* output) { |
| 88 if (input.direction == kDirectionIn) { |
| 89 const int* length = input.length.get(); |
| 90 if (length) { |
| 91 *output = *length; |
| 92 return true; |
| 93 } |
| 94 } else if (input.direction == kDirectionOut) { |
| 95 if (input.data.get()) { |
| 96 *output = input.data->size(); |
| 97 return true; |
| 98 } |
| 99 } |
| 100 return false; |
| 101 } |
| 102 |
| 103 template<class T> |
| 104 static scoped_refptr<net::IOBuffer> CreateBufferForTransfer(const T& input) { |
| 105 unsigned int size = 0; |
| 106 if (!GetTransferSize(input, &size)) { |
| 107 return NULL; |
| 108 } |
| 109 |
| 110 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(size); |
| 111 if (!input.data.get()) { |
| 112 return buffer; |
| 113 } |
| 114 |
| 115 const vector<int>& input_buffer = *input.data.get(); |
| 116 for (unsigned int i = 0; i < size; ++i) { |
| 117 buffer->data()[i] = input_buffer[i]; |
| 118 } |
| 119 |
| 120 return buffer; |
| 121 } |
| 122 |
| 123 } // namespace |
| 124 |
| 125 namespace extensions { |
| 126 |
| 127 UsbDeviceResource::UsbDeviceResource(APIResourceEventNotifier* notifier, |
| 128 UsbDevice* device) |
| 129 : APIResource(APIResource::UsbDeviceResource, notifier), device_(device) {} |
| 130 |
| 131 UsbDeviceResource::~UsbDeviceResource() {} |
| 132 |
| 133 void UsbDeviceResource::ControlTransfer(const ControlTransferInfo& transfer) { |
| 134 UsbDevice::TransferDirection direction; |
| 135 UsbDevice::TransferRequestType request_type; |
| 136 UsbDevice::TransferRecipient recipient; |
| 137 unsigned int size; |
| 138 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
| 139 |
| 140 if (!ConvertDirection(transfer.direction, &direction) || |
| 141 !ConvertRequestType(transfer.request_type, &request_type) || |
| 142 !ConvertRecipient(transfer.recipient, &recipient) || |
| 143 !GetTransferSize(transfer, &size) || !buffer) { |
| 144 LOG(INFO) << "Malformed transfer parameters."; |
| 145 return; |
| 146 } |
| 147 |
| 148 device_->ControlTransfer(direction, request_type, recipient, transfer.request, |
| 149 transfer.value, transfer.index, buffer, size, 0, |
| 150 base::Bind(&UsbDeviceResource::TransferComplete, |
| 151 base::Unretained(this), buffer, size)); |
| 152 } |
| 153 |
| 154 void UsbDeviceResource::InterruptTransfer(const GenericTransferInfo& transfer) { |
| 155 unsigned int size; |
| 156 UsbDevice::TransferDirection direction; |
| 157 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
| 158 |
| 159 if (!ConvertDirection(transfer.direction, &direction) || |
| 160 !GetTransferSize(transfer, &size) || !buffer) { |
| 161 LOG(INFO) << "Malformed transfer parameters."; |
| 162 return; |
| 163 } |
| 164 |
| 165 device_->InterruptTransfer(direction, transfer.endpoint, buffer, size, 0, |
| 166 base::Bind(&UsbDeviceResource::TransferComplete, |
| 167 base::Unretained(this), buffer, size)); |
| 168 } |
| 169 |
| 170 void UsbDeviceResource::BulkTransfer(const GenericTransferInfo& transfer) { |
| 171 unsigned int size; |
| 172 UsbDevice::TransferDirection direction; |
| 173 scoped_refptr<net::IOBuffer> buffer = CreateBufferForTransfer(transfer); |
| 174 |
| 175 if (!ConvertDirection(transfer.direction, &direction) || |
| 176 !GetTransferSize(transfer, &size) || !buffer) { |
| 177 LOG(INFO) << "Malformed transfer parameters."; |
| 178 return; |
| 179 } |
| 180 |
| 181 device_->BulkTransfer(direction, transfer.endpoint, buffer, size, 0, |
| 182 base::Bind(&UsbDeviceResource::TransferComplete, |
| 183 base::Unretained(this), buffer, size)); |
| 184 } |
| 185 |
| 186 void UsbDeviceResource::TransferComplete(net::IOBuffer* buffer, |
| 187 const size_t length, |
| 188 int success) { |
| 189 if (buffer) { |
| 190 base::ListValue *const response_buffer = new base::ListValue(); |
| 191 for (unsigned int i = 0; i < length; ++i) { |
| 192 const uint8_t value = buffer->data()[i] & 0xFF; |
| 193 response_buffer->Append(base::Value::CreateIntegerValue(value)); |
| 194 } |
| 195 event_notifier()->OnTransferComplete(success, response_buffer); |
| 196 } |
| 197 } |
| 198 |
| 199 } // namespace extensions |
OLD | NEW |