| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/usb/usb_device_handle.h" | 5 #include "components/usb_service/usb_device_handle.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/strings/string16.h" | 12 #include "base/strings/string16.h" |
| 13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
| 14 #include "chrome/browser/usb/usb_context.h" | 14 #include "components/usb_service/usb_context.h" |
| 15 #include "chrome/browser/usb/usb_device.h" | 15 #include "components/usb_service/usb_device.h" |
| 16 #include "chrome/browser/usb/usb_interface.h" | 16 #include "components/usb_service/usb_interface.h" |
| 17 #include "chrome/browser/usb/usb_service.h" | 17 #include "components/usb_service/usb_service.h" |
| 18 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
| 19 #include "third_party/libusb/src/libusb/libusb.h" | 19 #include "third_party/libusb/src/libusb/libusb.h" |
| 20 | 20 |
| 21 using content::BrowserThread; | 21 using content::BrowserThread; |
| 22 void HandleTransferCompletion(PlatformUsbTransferHandle transfer); | 22 |
| 23 namespace usb_service { |
| 24 |
| 25 void HandleTransferCompletion(usb_service::PlatformUsbTransferHandle transfer); |
| 23 | 26 |
| 24 namespace { | 27 namespace { |
| 25 | 28 |
| 26 static uint8 ConvertTransferDirection( | 29 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { |
| 27 const UsbEndpointDirection direction) { | |
| 28 switch (direction) { | 30 switch (direction) { |
| 29 case USB_DIRECTION_INBOUND: | 31 case USB_DIRECTION_INBOUND: |
| 30 return LIBUSB_ENDPOINT_IN; | 32 return LIBUSB_ENDPOINT_IN; |
| 31 case USB_DIRECTION_OUTBOUND: | 33 case USB_DIRECTION_OUTBOUND: |
| 32 return LIBUSB_ENDPOINT_OUT; | 34 return LIBUSB_ENDPOINT_OUT; |
| 33 default: | 35 default: |
| 34 NOTREACHED(); | 36 NOTREACHED(); |
| 35 return LIBUSB_ENDPOINT_IN; | 37 return LIBUSB_ENDPOINT_IN; |
| 36 } | 38 } |
| 37 } | 39 } |
| 38 | 40 |
| 39 static uint8 CreateRequestType(const UsbEndpointDirection direction, | 41 static uint8 CreateRequestType( |
| 42 const UsbEndpointDirection direction, |
| 40 const UsbDeviceHandle::TransferRequestType request_type, | 43 const UsbDeviceHandle::TransferRequestType request_type, |
| 41 const UsbDeviceHandle::TransferRecipient recipient) { | 44 const UsbDeviceHandle::TransferRecipient recipient) { |
| 42 uint8 result = ConvertTransferDirection(direction); | 45 uint8 result = ConvertTransferDirection(direction); |
| 43 | 46 |
| 44 switch (request_type) { | 47 switch (request_type) { |
| 45 case UsbDeviceHandle::STANDARD: | 48 case UsbDeviceHandle::STANDARD: |
| 46 result |= LIBUSB_REQUEST_TYPE_STANDARD; | 49 result |= LIBUSB_REQUEST_TYPE_STANDARD; |
| 47 break; | 50 break; |
| 48 case UsbDeviceHandle::CLASS: | 51 case UsbDeviceHandle::CLASS: |
| 49 result |= LIBUSB_REQUEST_TYPE_CLASS; | 52 result |= LIBUSB_REQUEST_TYPE_CLASS; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 case LIBUSB_TRANSFER_OVERFLOW: | 93 case LIBUSB_TRANSFER_OVERFLOW: |
| 91 return USB_TRANSFER_OVERFLOW; | 94 return USB_TRANSFER_OVERFLOW; |
| 92 case LIBUSB_TRANSFER_CANCELLED: | 95 case LIBUSB_TRANSFER_CANCELLED: |
| 93 return USB_TRANSFER_CANCELLED; | 96 return USB_TRANSFER_CANCELLED; |
| 94 default: | 97 default: |
| 95 NOTREACHED(); | 98 NOTREACHED(); |
| 96 return USB_TRANSFER_ERROR; | 99 return USB_TRANSFER_ERROR; |
| 97 } | 100 } |
| 98 } | 101 } |
| 99 | 102 |
| 100 static void LIBUSB_CALL PlatformTransferCompletionCallback( | 103 static void LIBUSB_CALL |
| 101 PlatformUsbTransferHandle transfer) { | 104 PlatformTransferCompletionCallback(PlatformUsbTransferHandle transfer) { |
| 102 BrowserThread::PostTask(BrowserThread::FILE, | 105 BrowserThread::PostTask(BrowserThread::FILE, |
| 103 FROM_HERE, | 106 FROM_HERE, |
| 104 base::Bind(HandleTransferCompletion, transfer)); | 107 base::Bind(HandleTransferCompletion, transfer)); |
| 105 } | 108 } |
| 106 | 109 |
| 107 } // namespace | 110 } // namespace |
| 108 | 111 |
| 109 void HandleTransferCompletion(PlatformUsbTransferHandle transfer) { | 112 void HandleTransferCompletion(PlatformUsbTransferHandle transfer) { |
| 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 111 UsbDeviceHandle* const device_handle = | 114 UsbDeviceHandle* const device_handle = |
| 112 reinterpret_cast<UsbDeviceHandle*>(transfer->user_data); | 115 reinterpret_cast<UsbDeviceHandle*>(transfer->user_data); |
| 113 CHECK(device_handle) << "Device handle is closed before transfer finishes."; | 116 CHECK(device_handle) << "Device handle is closed before transfer finishes."; |
| 114 device_handle->TransferComplete(transfer); | 117 device_handle->TransferComplete(transfer); |
| 115 libusb_free_transfer(transfer); | 118 libusb_free_transfer(transfer); |
| 116 } | 119 } |
| 117 | 120 |
| 118 | |
| 119 class UsbDeviceHandle::InterfaceClaimer | 121 class UsbDeviceHandle::InterfaceClaimer |
| 120 : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> { | 122 : public base::RefCountedThreadSafe<UsbDeviceHandle::InterfaceClaimer> { |
| 121 public: | 123 public: |
| 122 InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle, | 124 InterfaceClaimer(const scoped_refptr<UsbDeviceHandle> handle, |
| 123 const int interface_number); | 125 const int interface_number); |
| 124 | 126 |
| 125 bool Claim() const; | 127 bool Claim() const; |
| 126 | 128 |
| 127 int alternate_setting() const { return alternate_setting_; } | 129 int alternate_setting() const { return alternate_setting_; } |
| 128 void set_alternate_setting(const int alternate_setting) { | 130 void set_alternate_setting(const int alternate_setting) { |
| 129 alternate_setting_ = alternate_setting; | 131 alternate_setting_ = alternate_setting; |
| 130 } | 132 } |
| 131 | 133 |
| 132 private: | 134 private: |
| 133 friend class UsbDevice; | 135 friend class UsbDevice; |
| 134 friend class base::RefCountedThreadSafe<InterfaceClaimer>; | 136 friend class base::RefCountedThreadSafe<InterfaceClaimer>; |
| 135 ~InterfaceClaimer(); | 137 ~InterfaceClaimer(); |
| 136 | 138 |
| 137 const scoped_refptr<UsbDeviceHandle> handle_; | 139 const scoped_refptr<UsbDeviceHandle> handle_; |
| 138 const int interface_number_; | 140 const int interface_number_; |
| 139 int alternate_setting_; | 141 int alternate_setting_; |
| 140 | 142 |
| 141 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); | 143 DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); |
| 142 }; | 144 }; |
| 143 | 145 |
| 144 UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer( | 146 UsbDeviceHandle::InterfaceClaimer::InterfaceClaimer( |
| 145 const scoped_refptr<UsbDeviceHandle> handle, const int interface_number) | 147 const scoped_refptr<UsbDeviceHandle> handle, |
| 148 const int interface_number) |
| 146 : handle_(handle), | 149 : handle_(handle), |
| 147 interface_number_(interface_number), | 150 interface_number_(interface_number), |
| 148 alternate_setting_(0) { | 151 alternate_setting_(0) { |
| 149 } | 152 } |
| 150 | 153 |
| 151 UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() { | 154 UsbDeviceHandle::InterfaceClaimer::~InterfaceClaimer() { |
| 152 libusb_release_interface(handle_->handle(), interface_number_); | 155 libusb_release_interface(handle_->handle(), interface_number_); |
| 153 } | 156 } |
| 154 | 157 |
| 155 bool UsbDeviceHandle::InterfaceClaimer::Claim() const { | 158 bool UsbDeviceHandle::InterfaceClaimer::Claim() const { |
| 156 return libusb_claim_interface(handle_->handle(), interface_number_) == 0; | 159 return libusb_claim_interface(handle_->handle(), interface_number_) == 0; |
| 157 } | 160 } |
| 158 | 161 |
| 159 struct UsbDeviceHandle::Transfer { | 162 struct UsbDeviceHandle::Transfer { |
| 160 Transfer(); | 163 Transfer(); |
| 161 ~Transfer(); | 164 ~Transfer(); |
| 162 | 165 |
| 163 UsbTransferType transfer_type; | 166 UsbTransferType transfer_type; |
| 164 scoped_refptr<net::IOBuffer> buffer; | 167 scoped_refptr<net::IOBuffer> buffer; |
| 165 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface; | 168 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> claimed_interface; |
| 166 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; | 169 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; |
| 167 size_t length; | 170 size_t length; |
| 168 UsbTransferCallback callback; | 171 UsbTransferCallback callback; |
| 169 }; | 172 }; |
| 170 | 173 |
| 171 UsbDeviceHandle::Transfer::Transfer() | 174 UsbDeviceHandle::Transfer::Transfer() |
| 172 : transfer_type(USB_TRANSFER_CONTROL), | 175 : transfer_type(USB_TRANSFER_CONTROL), length(0) { |
| 173 length(0) { | |
| 174 } | 176 } |
| 175 | 177 |
| 176 UsbDeviceHandle::Transfer::~Transfer() {} | 178 UsbDeviceHandle::Transfer::~Transfer() { |
| 179 } |
| 177 | 180 |
| 178 UsbDeviceHandle::UsbDeviceHandle( | 181 UsbDeviceHandle::UsbDeviceHandle(scoped_refptr<UsbContext> context, |
| 179 scoped_refptr<UsbContext> context, | 182 UsbDevice* device, |
| 180 UsbDevice* device, | 183 PlatformUsbDeviceHandle handle, |
| 181 PlatformUsbDeviceHandle handle, | 184 scoped_refptr<UsbConfigDescriptor> interfaces) |
| 182 scoped_refptr<UsbConfigDescriptor> interfaces) | |
| 183 : device_(device), | 185 : device_(device), |
| 184 handle_(handle), | 186 handle_(handle), |
| 185 interfaces_(interfaces), | 187 interfaces_(interfaces), |
| 186 context_(context) { | 188 context_(context) { |
| 187 DCHECK(thread_checker_.CalledOnValidThread()); | 189 DCHECK(thread_checker_.CalledOnValidThread()); |
| 188 DCHECK(handle) << "Cannot create device with NULL handle."; | 190 DCHECK(handle) << "Cannot create device with NULL handle."; |
| 189 DCHECK(interfaces_) << "Unabled to list interfaces"; | 191 DCHECK(interfaces_) << "Unabled to list interfaces"; |
| 190 } | 192 } |
| 191 | 193 |
| 192 UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) { | 194 UsbDeviceHandle::UsbDeviceHandle() : device_(NULL), handle_(NULL) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 212 void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) { | 214 void UsbDeviceHandle::TransferComplete(PlatformUsbTransferHandle handle) { |
| 213 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; | 215 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
| 214 | 216 |
| 215 Transfer transfer = transfers_[handle]; | 217 Transfer transfer = transfers_[handle]; |
| 216 transfers_.erase(handle); | 218 transfers_.erase(handle); |
| 217 | 219 |
| 218 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; | 220 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; |
| 219 size_t actual_length = | 221 size_t actual_length = |
| 220 static_cast<size_t>(std::max(handle->actual_length, 0)); | 222 static_cast<size_t>(std::max(handle->actual_length, 0)); |
| 221 | 223 |
| 222 DCHECK(transfer.length >= actual_length) << | 224 DCHECK(transfer.length >= actual_length) |
| 223 "data too big for our buffer (libusb failure?)"; | 225 << "data too big for our buffer (libusb failure?)"; |
| 224 | 226 |
| 225 scoped_refptr<net::IOBuffer> buffer = transfer.buffer; | 227 scoped_refptr<net::IOBuffer> buffer = transfer.buffer; |
| 226 switch (transfer.transfer_type) { | 228 switch (transfer.transfer_type) { |
| 227 case USB_TRANSFER_CONTROL: | 229 case USB_TRANSFER_CONTROL: |
| 228 // If the transfer is a control transfer we do not expose the control | 230 // If the transfer is a control transfer we do not expose the control |
| 229 // setup header to the caller. This logic strips off the header if | 231 // setup header to the caller. This logic strips off the header if |
| 230 // present before invoking the callback provided with the transfer. | 232 // present before invoking the callback provided with the transfer. |
| 231 if (actual_length > 0) { | 233 if (actual_length > 0) { |
| 232 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) << | 234 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) |
| 233 "buffer was not correctly set: too small for the control header"; | 235 << "buffer was not correctly set: too small for the control header"; |
| 234 | 236 |
| 235 if (transfer.length >= actual_length && | 237 if (transfer.length >= actual_length && |
| 236 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { | 238 actual_length >= LIBUSB_CONTROL_SETUP_SIZE) { |
| 237 // If the payload is zero bytes long, pad out the allocated buffer | 239 // If the payload is zero bytes long, pad out the allocated buffer |
| 238 // size to one byte so that an IOBuffer of that size can be allocated. | 240 // size to one byte so that an IOBuffer of that size can be allocated. |
| 239 scoped_refptr<net::IOBuffer> resized_buffer = new net::IOBuffer( | 241 scoped_refptr<net::IOBuffer> resized_buffer = |
| 240 std::max(actual_length, static_cast<size_t>(1))); | 242 new net::IOBuffer(static_cast<int>( |
| 243 std::max(actual_length, static_cast<size_t>(1)))); |
| 241 memcpy(resized_buffer->data(), | 244 memcpy(resized_buffer->data(), |
| 242 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, | 245 buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
| 243 actual_length); | 246 actual_length); |
| 244 buffer = resized_buffer; | 247 buffer = resized_buffer; |
| 245 } | 248 } |
| 246 } | 249 } |
| 247 break; | 250 break; |
| 248 | 251 |
| 249 case USB_TRANSFER_ISOCHRONOUS: | 252 case USB_TRANSFER_ISOCHRONOUS: |
| 250 // Isochronous replies might carry data in the different isoc packets even | 253 // Isochronous replies might carry data in the different isoc packets even |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 ConvertTransferStatus(handle->status), | 291 ConvertTransferStatus(handle->status), |
| 289 buffer, | 292 buffer, |
| 290 actual_length)); | 293 actual_length)); |
| 291 | 294 |
| 292 // Must release interface first before actually delete this. | 295 // Must release interface first before actually delete this. |
| 293 transfer.claimed_interface = NULL; | 296 transfer.claimed_interface = NULL; |
| 294 } | 297 } |
| 295 | 298 |
| 296 bool UsbDeviceHandle::ClaimInterface(const int interface_number) { | 299 bool UsbDeviceHandle::ClaimInterface(const int interface_number) { |
| 297 DCHECK(thread_checker_.CalledOnValidThread()); | 300 DCHECK(thread_checker_.CalledOnValidThread()); |
| 298 if (!device_) return false; | 301 if (!device_) |
| 299 if (ContainsKey(claimed_interfaces_, interface_number)) return true; | 302 return false; |
| 303 if (ContainsKey(claimed_interfaces_, interface_number)) |
| 304 return true; |
| 300 | 305 |
| 301 scoped_refptr<InterfaceClaimer> claimer = | 306 scoped_refptr<InterfaceClaimer> claimer = |
| 302 new InterfaceClaimer(this, interface_number); | 307 new InterfaceClaimer(this, interface_number); |
| 303 | 308 |
| 304 if (claimer->Claim()) { | 309 if (claimer->Claim()) { |
| 305 claimed_interfaces_[interface_number]= claimer; | 310 claimed_interfaces_[interface_number] = claimer; |
| 306 RefreshEndpointMap(); | 311 RefreshEndpointMap(); |
| 307 return true; | 312 return true; |
| 308 } | 313 } |
| 309 return false; | 314 return false; |
| 310 } | 315 } |
| 311 | 316 |
| 312 bool UsbDeviceHandle::ReleaseInterface(const int interface_number) { | 317 bool UsbDeviceHandle::ReleaseInterface(const int interface_number) { |
| 313 DCHECK(thread_checker_.CalledOnValidThread()); | 318 DCHECK(thread_checker_.CalledOnValidThread()); |
| 314 if (!device_) return false; | 319 if (!device_) |
| 315 if (!ContainsKey(claimed_interfaces_, interface_number)) return false; | 320 return false; |
| 321 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 322 return false; |
| 316 | 323 |
| 317 // Cancel all the transfers on that interface. | 324 // Cancel all the transfers on that interface. |
| 318 InterfaceClaimer* interface_claimer = | 325 InterfaceClaimer* interface_claimer = |
| 319 claimed_interfaces_[interface_number].get(); | 326 claimed_interfaces_[interface_number].get(); |
| 320 for (TransferMap::iterator it = transfers_.begin(); | 327 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
| 321 it != transfers_.end(); ++it) { | 328 ++it) { |
| 322 if (it->second.claimed_interface.get() == interface_claimer) | 329 if (it->second.claimed_interface.get() == interface_claimer) |
| 323 libusb_cancel_transfer(it->first); | 330 libusb_cancel_transfer(it->first); |
| 324 } | 331 } |
| 325 claimed_interfaces_.erase(interface_number); | 332 claimed_interfaces_.erase(interface_number); |
| 326 | 333 |
| 327 RefreshEndpointMap(); | 334 RefreshEndpointMap(); |
| 328 return true; | 335 return true; |
| 329 } | 336 } |
| 330 | 337 |
| 331 bool UsbDeviceHandle::SetInterfaceAlternateSetting( | 338 bool UsbDeviceHandle::SetInterfaceAlternateSetting( |
| 332 const int interface_number, | 339 const int interface_number, |
| 333 const int alternate_setting) { | 340 const int alternate_setting) { |
| 334 DCHECK(thread_checker_.CalledOnValidThread()); | 341 DCHECK(thread_checker_.CalledOnValidThread()); |
| 335 if (!device_) return false; | 342 if (!device_) |
| 336 if (!ContainsKey(claimed_interfaces_, interface_number)) return false; | 343 return false; |
| 337 const int rv = libusb_set_interface_alt_setting(handle_, | 344 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 338 interface_number, alternate_setting); | 345 return false; |
| 346 const int rv = libusb_set_interface_alt_setting( |
| 347 handle_, interface_number, alternate_setting); |
| 339 if (rv == 0) { | 348 if (rv == 0) { |
| 340 claimed_interfaces_[interface_number]-> | 349 claimed_interfaces_[interface_number]->set_alternate_setting( |
| 341 set_alternate_setting(alternate_setting); | 350 alternate_setting); |
| 342 RefreshEndpointMap(); | 351 RefreshEndpointMap(); |
| 343 return true; | 352 return true; |
| 344 } | 353 } |
| 345 return false; | 354 return false; |
| 346 } | 355 } |
| 347 | 356 |
| 348 bool UsbDeviceHandle::ResetDevice() { | 357 bool UsbDeviceHandle::ResetDevice() { |
| 349 DCHECK(thread_checker_.CalledOnValidThread()); | 358 DCHECK(thread_checker_.CalledOnValidThread()); |
| 350 if (!device_) return false; | 359 if (!device_) |
| 360 return false; |
| 351 | 361 |
| 352 return libusb_reset_device(handle_) == 0; | 362 return libusb_reset_device(handle_) == 0; |
| 353 } | 363 } |
| 354 | 364 |
| 355 bool UsbDeviceHandle::GetSerial(base::string16* serial) { | 365 bool UsbDeviceHandle::GetSerial(base::string16* serial) { |
| 356 DCHECK(thread_checker_.CalledOnValidThread()); | 366 DCHECK(thread_checker_.CalledOnValidThread()); |
| 357 PlatformUsbDevice device = libusb_get_device(handle_); | 367 PlatformUsbDevice device = libusb_get_device(handle_); |
| 358 libusb_device_descriptor desc; | 368 libusb_device_descriptor desc; |
| 359 | 369 |
| 360 if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) | 370 if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) |
| 361 return false; | 371 return false; |
| 362 | 372 |
| 363 if (desc.iSerialNumber == 0) | 373 if (desc.iSerialNumber == 0) |
| 364 return false; | 374 return false; |
| 365 | 375 |
| 366 // Getting supported language ID. | 376 // Getting supported language ID. |
| 367 uint16 langid[128] = { 0 }; | 377 uint16 langid[128] = {0}; |
| 368 | 378 |
| 369 int size = libusb_get_string_descriptor( | 379 int size = |
| 370 handle_, 0, 0, | 380 libusb_get_string_descriptor(handle_, |
| 371 reinterpret_cast<unsigned char*>(&langid[0]), sizeof(langid)); | 381 0, |
| 382 0, |
| 383 reinterpret_cast<unsigned char*>(&langid[0]), |
| 384 sizeof(langid)); |
| 372 if (size < 0) | 385 if (size < 0) |
| 373 return false; | 386 return false; |
| 374 | 387 |
| 375 int language_count = (size - 2) / 2; | 388 int language_count = (size - 2) / 2; |
| 376 | 389 |
| 377 for (int i = 1; i <= language_count; ++i) { | 390 for (int i = 1; i <= language_count; ++i) { |
| 378 // Get the string using language ID. | 391 // Get the string using language ID. |
| 379 base::char16 text[256] = { 0 }; | 392 base::char16 text[256] = {0}; |
| 380 size = libusb_get_string_descriptor( | 393 size = |
| 381 handle_, desc.iSerialNumber, langid[i], | 394 libusb_get_string_descriptor(handle_, |
| 382 reinterpret_cast<unsigned char*>(&text[0]), sizeof(text)); | 395 desc.iSerialNumber, |
| 396 langid[i], |
| 397 reinterpret_cast<unsigned char*>(&text[0]), |
| 398 sizeof(text)); |
| 383 if (size <= 2) | 399 if (size <= 2) |
| 384 continue; | 400 continue; |
| 385 if ((text[0] >> 8) != LIBUSB_DT_STRING) | 401 if ((text[0] >> 8) != LIBUSB_DT_STRING) |
| 386 continue; | 402 continue; |
| 387 if ((text[0] & 255) > size) | 403 if ((text[0] & 255) > size) |
| 388 continue; | 404 continue; |
| 389 | 405 |
| 390 size = size / 2 - 1; | 406 size = size / 2 - 1; |
| 391 *serial = base::string16(text + 1, size); | 407 *serial = base::string16(text + 1, size); |
| 392 return true; | 408 return true; |
| 393 } | 409 } |
| 394 return false; | 410 return false; |
| 395 } | 411 } |
| 396 | 412 |
| 397 void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction, | 413 void UsbDeviceHandle::ControlTransfer(const UsbEndpointDirection direction, |
| 398 const TransferRequestType request_type, const TransferRecipient recipient, | 414 const TransferRequestType request_type, |
| 399 const uint8 request, const uint16 value, const uint16 index, | 415 const TransferRecipient recipient, |
| 400 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, | 416 const uint8 request, |
| 401 const UsbTransferCallback& callback) { | 417 const uint16 value, |
| 418 const uint16 index, |
| 419 net::IOBuffer* buffer, |
| 420 const size_t length, |
| 421 const unsigned int timeout, |
| 422 const UsbTransferCallback& callback) { |
| 402 if (!device_) { | 423 if (!device_) { |
| 403 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 424 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 404 return; | 425 return; |
| 405 } | 426 } |
| 406 | 427 |
| 407 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; | 428 const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; |
| 408 scoped_refptr<net::IOBuffer> resized_buffer(new net::IOBufferWithSize( | 429 scoped_refptr<net::IOBuffer> resized_buffer( |
| 409 resized_length)); | 430 new net::IOBufferWithSize(static_cast<int>(resized_length))); |
| 410 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, buffer->data(), | 431 if (!resized_buffer) { |
| 411 length); | 432 callback.Run(USB_TRANSFER_ERROR, buffer, 0); |
| 433 return; |
| 434 } |
| 435 memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
| 436 buffer->data(), |
| 437 static_cast<int>(length)); |
| 412 | 438 |
| 413 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 439 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
| 414 const uint8 converted_type = CreateRequestType(direction, request_type, | 440 const uint8 converted_type = |
| 415 recipient); | 441 CreateRequestType(direction, request_type, recipient); |
| 416 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), | 442 libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), |
| 417 converted_type, request, value, index, length); | 443 converted_type, |
| 418 libusb_fill_control_transfer( | 444 request, |
| 419 transfer, | 445 value, |
| 420 handle_, | 446 index, |
| 421 reinterpret_cast<uint8*>(resized_buffer->data()), | 447 static_cast<int16>(length)); |
| 422 PlatformTransferCompletionCallback, | 448 libusb_fill_control_transfer(transfer, |
| 423 this, | 449 handle_, |
| 424 timeout); | 450 reinterpret_cast<uint8*>(resized_buffer->data()), |
| 451 PlatformTransferCompletionCallback, |
| 452 this, |
| 453 timeout); |
| 425 | 454 |
| 426 BrowserThread::PostTask( | 455 BrowserThread::PostTask(BrowserThread::FILE, |
| 427 BrowserThread::FILE, | 456 FROM_HERE, |
| 428 FROM_HERE, | 457 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
| 429 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 458 this, |
| 430 this, | 459 transfer, |
| 431 transfer, | 460 USB_TRANSFER_CONTROL, |
| 432 USB_TRANSFER_CONTROL, | 461 resized_buffer, |
| 433 resized_buffer, | 462 resized_length, |
| 434 resized_length, | 463 base::MessageLoopProxy::current(), |
| 435 base::MessageLoopProxy::current(), | 464 callback)); |
| 436 callback)); | |
| 437 } | 465 } |
| 438 | 466 |
| 439 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction, | 467 void UsbDeviceHandle::BulkTransfer(const UsbEndpointDirection direction, |
| 440 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 468 const uint8 endpoint, |
| 441 const unsigned int timeout, const UsbTransferCallback& callback) { | 469 net::IOBuffer* buffer, |
| 470 const size_t length, |
| 471 const unsigned int timeout, |
| 472 const UsbTransferCallback& callback) { |
| 442 if (!device_) { | 473 if (!device_) { |
| 443 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 474 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 444 return; | 475 return; |
| 445 } | 476 } |
| 446 | 477 |
| 447 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 478 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
| 448 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 479 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 449 libusb_fill_bulk_transfer(transfer, handle_, new_endpoint, | 480 libusb_fill_bulk_transfer(transfer, |
| 450 reinterpret_cast<uint8*>(buffer->data()), length, | 481 handle_, |
| 451 PlatformTransferCompletionCallback, this, timeout); | 482 new_endpoint, |
| 483 reinterpret_cast<uint8*>(buffer->data()), |
| 484 static_cast<int>(length), |
| 485 PlatformTransferCompletionCallback, |
| 486 this, |
| 487 timeout); |
| 452 | 488 |
| 453 BrowserThread::PostTask( | 489 BrowserThread::PostTask(BrowserThread::FILE, |
| 454 BrowserThread::FILE, | 490 FROM_HERE, |
| 455 FROM_HERE, | 491 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
| 456 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 492 this, |
| 457 this, | 493 transfer, |
| 458 transfer, | 494 USB_TRANSFER_BULK, |
| 459 USB_TRANSFER_BULK, | 495 make_scoped_refptr(buffer), |
| 460 make_scoped_refptr(buffer), | 496 length, |
| 461 length, | 497 base::MessageLoopProxy::current(), |
| 462 base::MessageLoopProxy::current(), | 498 callback)); |
| 463 callback)); | |
| 464 } | 499 } |
| 465 | 500 |
| 466 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction, | 501 void UsbDeviceHandle::InterruptTransfer(const UsbEndpointDirection direction, |
| 467 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 502 const uint8 endpoint, |
| 468 const unsigned int timeout, const UsbTransferCallback& callback) { | 503 net::IOBuffer* buffer, |
| 504 const size_t length, |
| 505 const unsigned int timeout, |
| 506 const UsbTransferCallback& callback) { |
| 469 if (!device_) { | 507 if (!device_) { |
| 470 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 508 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 471 return; | 509 return; |
| 472 } | 510 } |
| 473 | 511 |
| 474 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); | 512 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); |
| 475 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 513 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 476 libusb_fill_interrupt_transfer(transfer, handle_, new_endpoint, | 514 libusb_fill_interrupt_transfer(transfer, |
| 477 reinterpret_cast<uint8*>(buffer->data()), length, | 515 handle_, |
| 478 PlatformTransferCompletionCallback, this, timeout); | 516 new_endpoint, |
| 479 BrowserThread::PostTask( | 517 reinterpret_cast<uint8*>(buffer->data()), |
| 480 BrowserThread::FILE, | 518 static_cast<int>(length), |
| 481 FROM_HERE, | 519 PlatformTransferCompletionCallback, |
| 482 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 520 this, |
| 483 this, | 521 timeout); |
| 484 transfer, | 522 BrowserThread::PostTask(BrowserThread::FILE, |
| 485 USB_TRANSFER_INTERRUPT, | 523 FROM_HERE, |
| 486 make_scoped_refptr(buffer), | 524 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
| 487 length, | 525 this, |
| 488 base::MessageLoopProxy::current(), | 526 transfer, |
| 489 callback)); | 527 USB_TRANSFER_INTERRUPT, |
| 528 make_scoped_refptr(buffer), |
| 529 length, |
| 530 base::MessageLoopProxy::current(), |
| 531 callback)); |
| 490 } | 532 } |
| 491 | 533 |
| 492 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction, | 534 void UsbDeviceHandle::IsochronousTransfer(const UsbEndpointDirection direction, |
| 493 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | 535 const uint8 endpoint, |
| 494 const unsigned int packets, const unsigned int packet_length, | 536 net::IOBuffer* buffer, |
| 495 const unsigned int timeout, const UsbTransferCallback& callback) { | 537 const size_t length, |
| 538 const unsigned int packets, |
| 539 const unsigned int packet_length, |
| 540 const unsigned int timeout, |
| 541 const UsbTransferCallback& callback) { |
| 496 if (!device_) { | 542 if (!device_) { |
| 497 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); | 543 callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); |
| 498 return; | 544 return; |
| 499 } | 545 } |
| 500 | 546 |
| 501 const uint64 total_length = packets * packet_length; | 547 const uint64 total_length = packets * packet_length; |
| 502 CHECK(packets <= length && total_length <= length) << | 548 CHECK(packets <= length && total_length <= length) |
| 503 "transfer length is too small"; | 549 << "transfer length is too small"; |
| 504 | 550 |
| 505 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); | 551 PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); |
| 506 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; | 552 const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; |
| 507 libusb_fill_iso_transfer(transfer, handle_, new_endpoint, | 553 libusb_fill_iso_transfer(transfer, |
| 508 reinterpret_cast<uint8*>(buffer->data()), length, packets, | 554 handle_, |
| 509 PlatformTransferCompletionCallback, this, timeout); | 555 new_endpoint, |
| 556 reinterpret_cast<uint8*>(buffer->data()), |
| 557 static_cast<int>(length), |
| 558 packets, |
| 559 PlatformTransferCompletionCallback, |
| 560 this, |
| 561 timeout); |
| 510 libusb_set_iso_packet_lengths(transfer, packet_length); | 562 libusb_set_iso_packet_lengths(transfer, packet_length); |
| 511 | 563 |
| 512 BrowserThread::PostTask( | 564 BrowserThread::PostTask(BrowserThread::FILE, |
| 513 BrowserThread::FILE, | 565 FROM_HERE, |
| 514 FROM_HERE, | 566 base::Bind(&UsbDeviceHandle::SubmitTransfer, |
| 515 base::Bind(&UsbDeviceHandle::SubmitTransfer, | 567 this, |
| 516 this, | 568 transfer, |
| 517 transfer, | 569 USB_TRANSFER_ISOCHRONOUS, |
| 518 USB_TRANSFER_ISOCHRONOUS, | 570 make_scoped_refptr(buffer), |
| 519 make_scoped_refptr(buffer), | 571 length, |
| 520 length, | 572 base::MessageLoopProxy::current(), |
| 521 base::MessageLoopProxy::current(), | 573 callback)); |
| 522 callback)); | |
| 523 } | 574 } |
| 524 | 575 |
| 525 void UsbDeviceHandle::RefreshEndpointMap() { | 576 void UsbDeviceHandle::RefreshEndpointMap() { |
| 526 DCHECK(thread_checker_.CalledOnValidThread()); | 577 DCHECK(thread_checker_.CalledOnValidThread()); |
| 527 endpoint_map_.clear(); | 578 endpoint_map_.clear(); |
| 528 for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin(); | 579 for (ClaimedInterfaceMap::iterator it = claimed_interfaces_.begin(); |
| 529 it != claimed_interfaces_.end(); ++it) { | 580 it != claimed_interfaces_.end(); |
| 581 ++it) { |
| 530 scoped_refptr<const UsbInterfaceAltSettingDescriptor> interface_desc = | 582 scoped_refptr<const UsbInterfaceAltSettingDescriptor> interface_desc = |
| 531 interfaces_->GetInterface(it->first)->GetAltSetting( | 583 interfaces_->GetInterface(it->first) |
| 532 it->second->alternate_setting()); | 584 ->GetAltSetting(it->second->alternate_setting()); |
| 533 for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) { | 585 for (size_t i = 0; i < interface_desc->GetNumEndpoints(); i++) { |
| 534 scoped_refptr<const UsbEndpointDescriptor> endpoint = | 586 scoped_refptr<const UsbEndpointDescriptor> endpoint = |
| 535 interface_desc->GetEndpoint(i); | 587 interface_desc->GetEndpoint(i); |
| 536 endpoint_map_[endpoint->GetAddress()] = it->first; | 588 endpoint_map_[endpoint->GetAddress()] = it->first; |
| 537 } | 589 } |
| 538 } | 590 } |
| 539 } | 591 } |
| 540 | 592 |
| 541 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> | 593 scoped_refptr<UsbDeviceHandle::InterfaceClaimer> |
| 542 UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { | 594 UsbDeviceHandle::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { |
| 543 unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; | 595 unsigned char address = endpoint & LIBUSB_ENDPOINT_ADDRESS_MASK; |
| 544 if (ContainsKey(endpoint_map_, address)) | 596 if (ContainsKey(endpoint_map_, address)) |
| 545 return claimed_interfaces_[endpoint_map_[address]]; | 597 return claimed_interfaces_[endpoint_map_[address]]; |
| 546 return NULL; | 598 return NULL; |
| 547 } | 599 } |
| 548 | 600 |
| 549 void UsbDeviceHandle::SubmitTransfer( | 601 void UsbDeviceHandle::SubmitTransfer( |
| 550 PlatformUsbTransferHandle handle, | 602 PlatformUsbTransferHandle handle, |
| 551 UsbTransferType transfer_type, | 603 UsbTransferType transfer_type, |
| 552 net::IOBuffer* buffer, | 604 net::IOBuffer* buffer, |
| 553 const size_t length, | 605 const size_t length, |
| 554 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | 606 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, |
| 555 const UsbTransferCallback& callback) { | 607 const UsbTransferCallback& callback) { |
| 556 DCHECK(thread_checker_.CalledOnValidThread()); | 608 DCHECK(thread_checker_.CalledOnValidThread()); |
| 557 if (!device_) { | 609 if (!device_) { |
| 558 message_loop_proxy->PostTask( | 610 message_loop_proxy->PostTask( |
| 559 FROM_HERE, | 611 FROM_HERE, |
| 560 base::Bind(callback, USB_TRANSFER_DISCONNECT, | 612 base::Bind( |
| 561 make_scoped_refptr(buffer), 0)); | 613 callback, USB_TRANSFER_DISCONNECT, make_scoped_refptr(buffer), 0)); |
| 562 } | 614 } |
| 563 | 615 |
| 564 Transfer transfer; | 616 Transfer transfer; |
| 565 transfer.transfer_type = transfer_type; | 617 transfer.transfer_type = transfer_type; |
| 566 transfer.buffer = buffer; | 618 transfer.buffer = buffer; |
| 567 transfer.length = length; | 619 transfer.length = length; |
| 568 transfer.callback = callback; | 620 transfer.callback = callback; |
| 569 transfer.message_loop_proxy = message_loop_proxy; | 621 transfer.message_loop_proxy = message_loop_proxy; |
| 570 | 622 |
| 571 // It's OK for this method to return NULL. libusb_submit_transfer will fail if | 623 // It's OK for this method to return NULL. libusb_submit_transfer will fail if |
| 572 // it requires an interface we didn't claim. | 624 // it requires an interface we didn't claim. |
| 573 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); | 625 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); |
| 574 | 626 |
| 575 if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) { | 627 if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) { |
| 576 transfers_[handle] = transfer; | 628 transfers_[handle] = transfer; |
| 577 } else { | 629 } else { |
| 578 message_loop_proxy->PostTask( | 630 message_loop_proxy->PostTask( |
| 579 FROM_HERE, | 631 FROM_HERE, |
| 580 base::Bind(callback, USB_TRANSFER_ERROR, | 632 base::Bind( |
| 581 make_scoped_refptr(buffer), 0)); | 633 callback, USB_TRANSFER_ERROR, make_scoped_refptr(buffer), 0)); |
| 582 } | 634 } |
| 583 } | 635 } |
| 584 | 636 |
| 585 void UsbDeviceHandle::InternalClose() { | 637 void UsbDeviceHandle::InternalClose() { |
| 586 DCHECK(thread_checker_.CalledOnValidThread()); | 638 DCHECK(thread_checker_.CalledOnValidThread()); |
| 587 if (!device_) return; | 639 if (!device_) |
| 640 return; |
| 588 | 641 |
| 589 // Cancel all the transfers. | 642 // Cancel all the transfers. |
| 590 for (TransferMap::iterator it = transfers_.begin(); | 643 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
| 591 it != transfers_.end(); ++it) { | 644 ++it) { |
| 592 // The callback will be called some time later. | 645 // The callback will be called some time later. |
| 593 libusb_cancel_transfer(it->first); | 646 libusb_cancel_transfer(it->first); |
| 594 } | 647 } |
| 595 | 648 |
| 596 // Attempt-release all the interfaces. | 649 // Attempt-release all the interfaces. |
| 597 // It will be retained until the transfer cancellation is finished. | 650 // It will be retained until the transfer cancellation is finished. |
| 598 claimed_interfaces_.clear(); | 651 claimed_interfaces_.clear(); |
| 599 | 652 |
| 600 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 653 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
| 601 // finish. | 654 // finish. |
| 602 device_ = NULL; | 655 device_ = NULL; |
| 603 } | 656 } |
| 657 |
| 658 } // namespace usb_service |
| OLD | NEW |