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 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). |
| 381 uint16 languages[128]; |
| 382 int size = libusb_get_string_descriptor( |
| 383 handle_, |
| 384 0, |
| 385 0, |
| 386 reinterpret_cast<unsigned char*>(&languages[0]), |
| 387 sizeof(languages)); |
| 388 if (size < 0) { |
| 389 VLOG(1) << "Failed to get list of supported languages: " |
| 390 << ConvertErrorToString(size); |
| 391 return false; |
| 392 } else if (size < 2) { |
| 393 VLOG(1) << "String descriptor zero has no header."; |
| 394 return false; |
| 395 // The first 2 bytes of the descriptor are the total length and type tag. |
| 396 } else if ((languages[0] & 0xff) != size) { |
| 397 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) |
| 398 << " != " << size; |
| 399 return false; |
| 400 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { |
| 401 VLOG(1) << "String descriptor zero is not a string descriptor."; |
| 402 return false; |
| 403 } |
| 404 |
| 405 languages_.assign(languages[1], languages[(size - 2) / 2]); |
| 406 return true; |
| 407 } |
| 408 |
| 409 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, |
| 410 base::string16* string) { |
| 411 if (!GetSupportedLanguages()) { |
| 412 return false; |
| 413 } |
| 414 |
| 415 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); |
| 416 if (it != strings_.end()) { |
| 417 *string = it->second; |
| 418 return true; |
| 419 } |
| 420 |
| 421 for (size_t i = 0; i < languages_.size(); ++i) { |
| 422 // Get the string using language ID. |
| 423 uint16 language_id = languages_[i]; |
| 424 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). |
| 425 base::char16 text[128]; |
| 426 int size = |
| 427 libusb_get_string_descriptor(handle_, |
| 428 string_id, |
| 429 language_id, |
| 430 reinterpret_cast<unsigned char*>(&text[0]), |
| 431 sizeof(text)); |
| 432 if (size < 0) { |
| 433 VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " |
| 434 << language_id << "): " << ConvertErrorToString(size); |
| 435 continue; |
| 436 } else if (size < 2) { |
| 437 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id |
| 438 << ") has no header."; |
| 439 continue; |
| 440 // The first 2 bytes of the descriptor are the total length and type tag. |
| 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 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { |
| 446 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id |
| 447 << ") is not a string descriptor."; |
| 448 continue; |
| 449 } |
| 450 |
| 451 *string = base::string16(text + 1, (size - 2) / 2); |
| 452 strings_[string_id] = *string; |
| 453 return true; |
| 454 } |
| 455 |
| 456 return false; |
| 457 } |
| 458 |
| 459 bool UsbDeviceHandleImpl::GetManufacturer(base::string16* manufacturer) { |
| 460 DCHECK(thread_checker_.CalledOnValidThread()); |
| 461 PlatformUsbDevice device = libusb_get_device(handle_); |
| 462 libusb_device_descriptor desc; |
| 463 |
| 464 // This is a non-blocking call as libusb has the descriptor in memory. |
| 465 const int rv = libusb_get_device_descriptor(device, &desc); |
| 466 if (rv != LIBUSB_SUCCESS) { |
| 467 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); |
| 468 return false; |
| 469 } |
| 470 |
| 471 if (desc.iManufacturer == 0) { |
| 472 return false; |
| 473 } |
| 474 |
| 475 return GetStringDescriptor(desc.iManufacturer, manufacturer); |
| 476 } |
| 477 |
| 478 bool UsbDeviceHandleImpl::GetProduct(base::string16* product) { |
| 479 DCHECK(thread_checker_.CalledOnValidThread()); |
| 480 PlatformUsbDevice device = libusb_get_device(handle_); |
| 481 libusb_device_descriptor desc; |
| 482 |
| 483 // This is a non-blocking call as libusb has the descriptor in memory. |
| 484 const int rv = libusb_get_device_descriptor(device, &desc); |
| 485 if (rv != LIBUSB_SUCCESS) { |
| 486 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); |
| 487 return false; |
| 488 } |
| 489 |
| 490 if (desc.iProduct == 0) { |
| 491 return false; |
| 492 } |
| 493 |
| 494 return GetStringDescriptor(desc.iProduct, product); |
| 495 } |
| 496 |
375 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { | 497 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { |
376 DCHECK(thread_checker_.CalledOnValidThread()); | 498 DCHECK(thread_checker_.CalledOnValidThread()); |
377 PlatformUsbDevice device = libusb_get_device(handle_); | 499 PlatformUsbDevice device = libusb_get_device(handle_); |
378 libusb_device_descriptor desc; | 500 libusb_device_descriptor desc; |
379 | 501 |
| 502 // This is a non-blocking call as libusb has the descriptor in memory. |
380 const int rv = libusb_get_device_descriptor(device, &desc); | 503 const int rv = libusb_get_device_descriptor(device, &desc); |
381 if (rv != LIBUSB_SUCCESS) { | 504 if (rv != LIBUSB_SUCCESS) { |
382 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | 505 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); |
383 return false; | 506 return false; |
384 } | 507 } |
385 | 508 |
386 if (desc.iSerialNumber == 0) | 509 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; | 510 return false; |
401 } | 511 } |
402 | 512 |
403 int language_count = (size - 2) / 2; | 513 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 } | 514 } |
432 | 515 |
433 void UsbDeviceHandleImpl::ControlTransfer( | 516 void UsbDeviceHandleImpl::ControlTransfer( |
434 const UsbEndpointDirection direction, | 517 const UsbEndpointDirection direction, |
435 const TransferRequestType request_type, | 518 const TransferRequestType request_type, |
436 const TransferRecipient recipient, | 519 const TransferRecipient recipient, |
437 const uint8 request, | 520 const uint8 request, |
438 const uint16 value, | 521 const uint16 value, |
439 const uint16 index, | 522 const uint16 index, |
440 net::IOBuffer* buffer, | 523 net::IOBuffer* buffer, |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 // Attempt-release all the interfaces. | 757 // Attempt-release all the interfaces. |
675 // It will be retained until the transfer cancellation is finished. | 758 // It will be retained until the transfer cancellation is finished. |
676 claimed_interfaces_.clear(); | 759 claimed_interfaces_.clear(); |
677 | 760 |
678 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 761 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
679 // finish. | 762 // finish. |
680 device_ = NULL; | 763 device_ = NULL; |
681 } | 764 } |
682 | 765 |
683 } // namespace usb_service | 766 } // namespace usb_service |
OLD | NEW |