OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/usb_service/usb_device_handle_impl.h" | 5 #include "components/usb_service/usb_device_handle_impl.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" |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 scoped_refptr<UsbContext> context, | 189 scoped_refptr<UsbContext> context, |
190 UsbDeviceImpl* device, | 190 UsbDeviceImpl* device, |
191 PlatformUsbDeviceHandle handle, | 191 PlatformUsbDeviceHandle handle, |
192 scoped_refptr<UsbConfigDescriptor> interfaces) | 192 scoped_refptr<UsbConfigDescriptor> interfaces) |
193 : device_(device), | 193 : device_(device), |
194 handle_(handle), | 194 handle_(handle), |
195 interfaces_(interfaces), | 195 interfaces_(interfaces), |
196 context_(context) { | 196 context_(context) { |
197 DCHECK(thread_checker_.CalledOnValidThread()); | 197 DCHECK(thread_checker_.CalledOnValidThread()); |
198 DCHECK(handle) << "Cannot create device with NULL handle."; | 198 DCHECK(handle) << "Cannot create device with NULL handle."; |
199 DCHECK(interfaces_) << "Unabled to list interfaces"; | 199 DCHECK(interfaces_) << "Unable to list interfaces"; |
200 } | 200 } |
201 | 201 |
202 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { | 202 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { |
203 DCHECK(thread_checker_.CalledOnValidThread()); | 203 DCHECK(thread_checker_.CalledOnValidThread()); |
204 | 204 |
205 libusb_close(handle_); | 205 libusb_close(handle_); |
206 handle_ = NULL; | 206 handle_ = NULL; |
207 } | 207 } |
208 | 208 |
209 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { | 209 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
365 if (!device_) | 365 if (!device_) |
366 return false; | 366 return false; |
367 | 367 |
368 const int rv = libusb_reset_device(handle_); | 368 const int rv = libusb_reset_device(handle_); |
369 if (rv != LIBUSB_SUCCESS) { | 369 if (rv != LIBUSB_SUCCESS) { |
370 VLOG(1) << "Failed to reset device: " << ConvertErrorToString(rv); | 370 VLOG(1) << "Failed to reset device: " << ConvertErrorToString(rv); |
371 } | 371 } |
372 return rv == LIBUSB_SUCCESS; | 372 return rv == LIBUSB_SUCCESS; |
373 } | 373 } |
374 | 374 |
375 bool UsbDeviceHandleImpl::GetSupportedLanguages() { | |
376 if (!languages_.empty()) { | |
377 return true; | |
378 } | |
379 | |
380 uint16 languages[256]; | |
Ken Rockot(use gerrit already)
2014/08/13 19:19:00
Only need 128 here and below.
Reilly Grant (use Gerrit)
2014/08/13 21:20:43
Done.
| |
381 int size = libusb_get_string_descriptor( | |
382 handle_, | |
383 0, | |
384 0, | |
385 reinterpret_cast<unsigned char*>(&languages[0]), | |
386 sizeof(languages)); | |
387 if (size < 0) { | |
388 VLOG(1) << "Failed to get list of supported languages: " | |
389 << ConvertErrorToString(size); | |
390 return false; | |
391 } else if (size < 2) { | |
392 VLOG(1) << "String descriptor zero has no header."; | |
393 return false; | |
394 } else if ((languages[0] & 0xff) != size) { | |
Ken Rockot(use gerrit already)
2014/08/13 19:19:00
Please add a comment documenting the contents of t
Reilly Grant (use Gerrit)
2014/08/13 21:20:43
Done.
| |
395 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) | |
396 << " != " << size; | |
397 return false; | |
398 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { | |
399 VLOG(1) << "String descriptor zero is not a string descriptor."; | |
400 return false; | |
401 } | |
402 | |
403 languages_.assign(languages[1], languages[(size - 2) / 2]); | |
404 return true; | |
405 } | |
406 | |
407 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, | |
408 base::string16* string) { | |
409 if (!GetSupportedLanguages()) { | |
410 return false; | |
411 } | |
412 | |
413 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); | |
414 if (it != strings_.end()) { | |
415 *string = it->second; | |
416 return true; | |
417 } | |
418 | |
419 for (size_t i = 0; i < languages_.size(); ++i) { | |
420 // Get the string using language ID. | |
421 uint16 language_id = languages_[i]; | |
422 base::char16 text[256]; | |
423 int size = | |
424 libusb_get_string_descriptor(handle_, | |
425 string_id, | |
426 language_id, | |
427 reinterpret_cast<unsigned char*>(&text[0]), | |
428 sizeof(text)); | |
429 if (size < 0) { | |
430 VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " | |
431 << language_id << "): " << ConvertErrorToString(size); | |
432 continue; | |
433 } else if (size < 2) { | |
434 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | |
435 << ") has no header."; | |
436 continue; | |
437 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { | |
438 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | |
439 << ") is not a string descriptor."; | |
440 continue; | |
441 } else if ((text[0] & 0xff) != size) { | |
442 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | |
443 << ") size mismatch: " << (text[0] & 0xff) << " != " << size; | |
444 continue; | |
445 } | |
446 | |
447 *string = base::string16(text + 1, (size - 2) / 2); | |
448 strings_[string_id] = *string; | |
449 return true; | |
450 } | |
451 | |
452 return false; | |
453 } | |
454 | |
455 bool UsbDeviceHandleImpl::GetManufacturer(base::string16* manufacturer) { | |
456 DCHECK(thread_checker_.CalledOnValidThread()); | |
457 PlatformUsbDevice device = libusb_get_device(handle_); | |
458 libusb_device_descriptor desc; | |
459 | |
460 // This is a non-blocking call as libusb has the descriptor in memory. | |
461 const int rv = libusb_get_device_descriptor(device, &desc); | |
462 if (rv != LIBUSB_SUCCESS) { | |
463 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | |
464 return false; | |
465 } | |
466 | |
467 if (desc.iManufacturer == 0) { | |
468 return false; | |
469 } | |
470 | |
471 return GetStringDescriptor(desc.iManufacturer, manufacturer); | |
472 } | |
473 | |
474 bool UsbDeviceHandleImpl::GetProduct(base::string16* product) { | |
475 DCHECK(thread_checker_.CalledOnValidThread()); | |
476 PlatformUsbDevice device = libusb_get_device(handle_); | |
477 libusb_device_descriptor desc; | |
478 | |
479 // This is a non-blocking call as libusb has the descriptor in memory. | |
480 const int rv = libusb_get_device_descriptor(device, &desc); | |
481 if (rv != LIBUSB_SUCCESS) { | |
482 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | |
483 return false; | |
484 } | |
485 | |
486 if (desc.iProduct == 0) { | |
487 return false; | |
488 } | |
489 | |
490 return GetStringDescriptor(desc.iProduct, product); | |
491 } | |
492 | |
375 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { | 493 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { |
376 DCHECK(thread_checker_.CalledOnValidThread()); | 494 DCHECK(thread_checker_.CalledOnValidThread()); |
377 PlatformUsbDevice device = libusb_get_device(handle_); | 495 PlatformUsbDevice device = libusb_get_device(handle_); |
378 libusb_device_descriptor desc; | 496 libusb_device_descriptor desc; |
379 | 497 |
498 // This is a non-blocking call as libusb has the descriptor in memory. | |
380 const int rv = libusb_get_device_descriptor(device, &desc); | 499 const int rv = libusb_get_device_descriptor(device, &desc); |
381 if (rv != LIBUSB_SUCCESS) { | 500 if (rv != LIBUSB_SUCCESS) { |
382 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | 501 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); |
383 return false; | 502 return false; |
384 } | 503 } |
385 | 504 |
386 if (desc.iSerialNumber == 0) | 505 if (desc.iSerialNumber == 0) { |
387 return false; | |
388 | |
389 // Getting supported language ID. | |
390 uint16 langid[128] = {0}; | |
391 | |
392 int size = | |
393 libusb_get_string_descriptor(handle_, | |
394 0, | |
395 0, | |
396 reinterpret_cast<unsigned char*>(&langid[0]), | |
397 sizeof(langid)); | |
398 if (size < 0) { | |
399 VLOG(1) << "Failed to get language IDs: " << ConvertErrorToString(size); | |
400 return false; | 506 return false; |
401 } | 507 } |
402 | 508 |
403 int language_count = (size - 2) / 2; | 509 return GetStringDescriptor(desc.iSerialNumber, serial); |
404 | |
405 for (int i = 1; i <= language_count; ++i) { | |
406 // Get the string using language ID. | |
407 base::char16 text[256] = {0}; | |
408 size = | |
409 libusb_get_string_descriptor(handle_, | |
410 desc.iSerialNumber, | |
411 langid[i], | |
412 reinterpret_cast<unsigned char*>(&text[0]), | |
413 sizeof(text)); | |
414 if (size < 0) { | |
415 VLOG(1) << "Failed to get serial number (langid " << langid[i] << "): " | |
416 << ConvertErrorToString(size); | |
417 continue; | |
418 } | |
419 if (size <= 2) | |
420 continue; | |
421 if ((text[0] >> 8) != LIBUSB_DT_STRING) | |
422 continue; | |
423 if ((text[0] & 255) > size) | |
424 continue; | |
425 | |
426 size = size / 2 - 1; | |
427 *serial = base::string16(text + 1, size); | |
428 return true; | |
429 } | |
430 return false; | |
431 } | 510 } |
432 | 511 |
433 void UsbDeviceHandleImpl::ControlTransfer( | 512 void UsbDeviceHandleImpl::ControlTransfer( |
434 const UsbEndpointDirection direction, | 513 const UsbEndpointDirection direction, |
435 const TransferRequestType request_type, | 514 const TransferRequestType request_type, |
436 const TransferRecipient recipient, | 515 const TransferRecipient recipient, |
437 const uint8 request, | 516 const uint8 request, |
438 const uint16 value, | 517 const uint16 value, |
439 const uint16 index, | 518 const uint16 index, |
440 net::IOBuffer* buffer, | 519 net::IOBuffer* buffer, |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 // Attempt-release all the interfaces. | 753 // Attempt-release all the interfaces. |
675 // It will be retained until the transfer cancellation is finished. | 754 // It will be retained until the transfer cancellation is finished. |
676 claimed_interfaces_.clear(); | 755 claimed_interfaces_.clear(); |
677 | 756 |
678 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 757 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
679 // finish. | 758 // finish. |
680 device_ = NULL; | 759 device_ = NULL; |
681 } | 760 } |
682 | 761 |
683 } // namespace usb_service | 762 } // namespace usb_service |
OLD | NEW |