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]; |
| 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) { |
| 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 |