| 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 "device/usb/usb_device_handle_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
| 14 #include "base/strings/string16.h" | 14 #include "base/strings/string16.h" |
| 15 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
| 16 #include "base/thread_task_runner_handle.h" | 16 #include "base/thread_task_runner_handle.h" |
| 17 #include "components/usb_service/usb_context.h" | 17 #include "device/usb/usb_context.h" |
| 18 #include "components/usb_service/usb_device_impl.h" | 18 #include "device/usb/usb_device_impl.h" |
| 19 #include "components/usb_service/usb_error.h" | 19 #include "device/usb/usb_error.h" |
| 20 #include "components/usb_service/usb_interface.h" | 20 #include "device/usb/usb_interface.h" |
| 21 #include "components/usb_service/usb_service.h" | 21 #include "device/usb/usb_service.h" |
| 22 #include "third_party/libusb/src/libusb/libusb.h" | 22 #include "third_party/libusb/src/libusb/libusb.h" |
| 23 | 23 |
| 24 namespace usb_service { | 24 namespace device { |
| 25 | 25 |
| 26 typedef libusb_device* PlatformUsbDevice; | 26 typedef libusb_device* PlatformUsbDevice; |
| 27 | 27 |
| 28 void HandleTransferCompletion(usb_service::PlatformUsbTransferHandle transfer); | 28 void HandleTransferCompletion(PlatformUsbTransferHandle transfer); |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 | 31 |
| 32 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { | 32 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { |
| 33 switch (direction) { | 33 switch (direction) { |
| 34 case USB_DIRECTION_INBOUND: | 34 case USB_DIRECTION_INBOUND: |
| 35 return LIBUSB_ENDPOINT_IN; | 35 return LIBUSB_ENDPOINT_IN; |
| 36 case USB_DIRECTION_OUTBOUND: | 36 case USB_DIRECTION_OUTBOUND: |
| 37 return LIBUSB_ENDPOINT_OUT; | 37 return LIBUSB_ENDPOINT_OUT; |
| 38 default: | 38 default: |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 alternate_setting_(0) { | 138 alternate_setting_(0) { |
| 139 } | 139 } |
| 140 | 140 |
| 141 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { | 141 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { |
| 142 libusb_release_interface(handle_->handle(), interface_number_); | 142 libusb_release_interface(handle_->handle(), interface_number_); |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { | 145 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { |
| 146 const int rv = libusb_claim_interface(handle_->handle(), interface_number_); | 146 const int rv = libusb_claim_interface(handle_->handle(), interface_number_); |
| 147 if (rv != LIBUSB_SUCCESS) { | 147 if (rv != LIBUSB_SUCCESS) { |
| 148 VLOG(1) << "Failed to claim interface: " << ConvertErrorToString(rv); | 148 VLOG(1) << "Failed to claim interface: " |
| 149 << ConvertPlatformUsbErrorToString(rv); |
| 149 } | 150 } |
| 150 return rv == LIBUSB_SUCCESS; | 151 return rv == LIBUSB_SUCCESS; |
| 151 } | 152 } |
| 152 | 153 |
| 153 struct UsbDeviceHandleImpl::Transfer { | 154 struct UsbDeviceHandleImpl::Transfer { |
| 154 Transfer(); | 155 Transfer(); |
| 155 ~Transfer(); | 156 ~Transfer(); |
| 156 | 157 |
| 157 void Complete(UsbTransferStatus status, size_t bytes_transferred); | 158 void Complete(UsbTransferStatus status, size_t bytes_transferred); |
| 158 | 159 |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 if (!ContainsKey(claimed_interfaces_, interface_number)) | 351 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 351 return false; | 352 return false; |
| 352 const int rv = libusb_set_interface_alt_setting( | 353 const int rv = libusb_set_interface_alt_setting( |
| 353 handle_, interface_number, alternate_setting); | 354 handle_, interface_number, alternate_setting); |
| 354 if (rv == LIBUSB_SUCCESS) { | 355 if (rv == LIBUSB_SUCCESS) { |
| 355 claimed_interfaces_[interface_number]->set_alternate_setting( | 356 claimed_interfaces_[interface_number]->set_alternate_setting( |
| 356 alternate_setting); | 357 alternate_setting); |
| 357 RefreshEndpointMap(); | 358 RefreshEndpointMap(); |
| 358 } else { | 359 } else { |
| 359 VLOG(1) << "Failed to set interface (" << interface_number << ", " | 360 VLOG(1) << "Failed to set interface (" << interface_number << ", " |
| 360 << alternate_setting << "): " << ConvertErrorToString(rv); | 361 << alternate_setting |
| 362 << "): " << ConvertPlatformUsbErrorToString(rv); |
| 361 } | 363 } |
| 362 return rv == LIBUSB_SUCCESS; | 364 return rv == LIBUSB_SUCCESS; |
| 363 } | 365 } |
| 364 | 366 |
| 365 bool UsbDeviceHandleImpl::ResetDevice() { | 367 bool UsbDeviceHandleImpl::ResetDevice() { |
| 366 DCHECK(thread_checker_.CalledOnValidThread()); | 368 DCHECK(thread_checker_.CalledOnValidThread()); |
| 367 if (!device_) | 369 if (!device_) |
| 368 return false; | 370 return false; |
| 369 | 371 |
| 370 const int rv = libusb_reset_device(handle_); | 372 const int rv = libusb_reset_device(handle_); |
| 371 if (rv != LIBUSB_SUCCESS) { | 373 if (rv != LIBUSB_SUCCESS) { |
| 372 VLOG(1) << "Failed to reset device: " << ConvertErrorToString(rv); | 374 VLOG(1) << "Failed to reset device: " |
| 375 << ConvertPlatformUsbErrorToString(rv); |
| 373 } | 376 } |
| 374 return rv == LIBUSB_SUCCESS; | 377 return rv == LIBUSB_SUCCESS; |
| 375 } | 378 } |
| 376 | 379 |
| 377 bool UsbDeviceHandleImpl::GetSupportedLanguages() { | 380 bool UsbDeviceHandleImpl::GetSupportedLanguages() { |
| 378 if (!languages_.empty()) { | 381 if (!languages_.empty()) { |
| 379 return true; | 382 return true; |
| 380 } | 383 } |
| 381 | 384 |
| 382 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). | 385 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). |
| 383 uint16 languages[128]; | 386 uint16 languages[128]; |
| 384 int size = libusb_get_string_descriptor( | 387 int size = libusb_get_string_descriptor( |
| 385 handle_, | 388 handle_, |
| 386 0, | 389 0, |
| 387 0, | 390 0, |
| 388 reinterpret_cast<unsigned char*>(&languages[0]), | 391 reinterpret_cast<unsigned char*>(&languages[0]), |
| 389 sizeof(languages)); | 392 sizeof(languages)); |
| 390 if (size < 0) { | 393 if (size < 0) { |
| 391 VLOG(1) << "Failed to get list of supported languages: " | 394 VLOG(1) << "Failed to get list of supported languages: " |
| 392 << ConvertErrorToString(size); | 395 << ConvertPlatformUsbErrorToString(size); |
| 393 return false; | 396 return false; |
| 394 } else if (size < 2) { | 397 } else if (size < 2) { |
| 395 VLOG(1) << "String descriptor zero has no header."; | 398 VLOG(1) << "String descriptor zero has no header."; |
| 396 return false; | 399 return false; |
| 397 // The first 2 bytes of the descriptor are the total length and type tag. | 400 // The first 2 bytes of the descriptor are the total length and type tag. |
| 398 } else if ((languages[0] & 0xff) != size) { | 401 } else if ((languages[0] & 0xff) != size) { |
| 399 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) | 402 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) |
| 400 << " != " << size; | 403 << " != " << size; |
| 401 return false; | 404 return false; |
| 402 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { | 405 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { |
| 403 VLOG(1) << "String descriptor zero is not a string descriptor."; | 406 VLOG(1) << "String descriptor zero is not a string descriptor."; |
| 404 return false; | 407 return false; |
| 405 } | 408 } |
| 406 | 409 |
| 407 languages_.assign(languages[1], languages[(size - 2) / 2]); | 410 languages_.assign(languages[1], languages[(size - 2) / 2]); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 426 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). | 429 // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). |
| 427 base::char16 text[128]; | 430 base::char16 text[128]; |
| 428 int size = | 431 int size = |
| 429 libusb_get_string_descriptor(handle_, | 432 libusb_get_string_descriptor(handle_, |
| 430 string_id, | 433 string_id, |
| 431 language_id, | 434 language_id, |
| 432 reinterpret_cast<unsigned char*>(&text[0]), | 435 reinterpret_cast<unsigned char*>(&text[0]), |
| 433 sizeof(text)); | 436 sizeof(text)); |
| 434 if (size < 0) { | 437 if (size < 0) { |
| 435 VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " | 438 VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " |
| 436 << language_id << "): " << ConvertErrorToString(size); | 439 << language_id << "): " << ConvertPlatformUsbErrorToString(size); |
| 437 continue; | 440 continue; |
| 438 } else if (size < 2) { | 441 } else if (size < 2) { |
| 439 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | 442 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id |
| 440 << ") has no header."; | 443 << ") has no header."; |
| 441 continue; | 444 continue; |
| 442 // The first 2 bytes of the descriptor are the total length and type tag. | 445 // The first 2 bytes of the descriptor are the total length and type tag. |
| 443 } else if ((text[0] & 0xff) != size) { | 446 } else if ((text[0] & 0xff) != size) { |
| 444 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | 447 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id |
| 445 << ") size mismatch: " << (text[0] & 0xff) << " != " << size; | 448 << ") size mismatch: " << (text[0] & 0xff) << " != " << size; |
| 446 continue; | 449 continue; |
| 447 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { | 450 } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { |
| 448 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id | 451 VLOG(1) << "String descriptor " << string_id << " (langid " << language_id |
| 449 << ") is not a string descriptor."; | 452 << ") is not a string descriptor."; |
| 450 continue; | 453 continue; |
| 451 } | 454 } |
| 452 | 455 |
| 453 *string = base::string16(text + 1, (size - 2) / 2); | 456 *string = base::string16(text + 1, (size - 2) / 2); |
| 454 strings_[string_id] = *string; | 457 strings_[string_id] = *string; |
| 455 return true; | 458 return true; |
| 456 } | 459 } |
| 457 | 460 |
| 458 return false; | 461 return false; |
| 459 } | 462 } |
| 460 | 463 |
| 461 bool UsbDeviceHandleImpl::GetManufacturer(base::string16* manufacturer) { | 464 bool UsbDeviceHandleImpl::GetManufacturer(base::string16* manufacturer) { |
| 462 DCHECK(thread_checker_.CalledOnValidThread()); | 465 DCHECK(thread_checker_.CalledOnValidThread()); |
| 463 PlatformUsbDevice device = libusb_get_device(handle_); | 466 PlatformUsbDevice device = libusb_get_device(handle_); |
| 464 libusb_device_descriptor desc; | 467 libusb_device_descriptor desc; |
| 465 | 468 |
| 466 // This is a non-blocking call as libusb has the descriptor in memory. | 469 // This is a non-blocking call as libusb has the descriptor in memory. |
| 467 const int rv = libusb_get_device_descriptor(device, &desc); | 470 const int rv = libusb_get_device_descriptor(device, &desc); |
| 468 if (rv != LIBUSB_SUCCESS) { | 471 if (rv != LIBUSB_SUCCESS) { |
| 469 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | 472 VLOG(1) << "Failed to read device descriptor: " |
| 473 << ConvertPlatformUsbErrorToString(rv); |
| 470 return false; | 474 return false; |
| 471 } | 475 } |
| 472 | 476 |
| 473 if (desc.iManufacturer == 0) { | 477 if (desc.iManufacturer == 0) { |
| 474 return false; | 478 return false; |
| 475 } | 479 } |
| 476 | 480 |
| 477 return GetStringDescriptor(desc.iManufacturer, manufacturer); | 481 return GetStringDescriptor(desc.iManufacturer, manufacturer); |
| 478 } | 482 } |
| 479 | 483 |
| 480 bool UsbDeviceHandleImpl::GetProduct(base::string16* product) { | 484 bool UsbDeviceHandleImpl::GetProduct(base::string16* product) { |
| 481 DCHECK(thread_checker_.CalledOnValidThread()); | 485 DCHECK(thread_checker_.CalledOnValidThread()); |
| 482 PlatformUsbDevice device = libusb_get_device(handle_); | 486 PlatformUsbDevice device = libusb_get_device(handle_); |
| 483 libusb_device_descriptor desc; | 487 libusb_device_descriptor desc; |
| 484 | 488 |
| 485 // This is a non-blocking call as libusb has the descriptor in memory. | 489 // This is a non-blocking call as libusb has the descriptor in memory. |
| 486 const int rv = libusb_get_device_descriptor(device, &desc); | 490 const int rv = libusb_get_device_descriptor(device, &desc); |
| 487 if (rv != LIBUSB_SUCCESS) { | 491 if (rv != LIBUSB_SUCCESS) { |
| 488 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | 492 VLOG(1) << "Failed to read device descriptor: " |
| 493 << ConvertPlatformUsbErrorToString(rv); |
| 489 return false; | 494 return false; |
| 490 } | 495 } |
| 491 | 496 |
| 492 if (desc.iProduct == 0) { | 497 if (desc.iProduct == 0) { |
| 493 return false; | 498 return false; |
| 494 } | 499 } |
| 495 | 500 |
| 496 return GetStringDescriptor(desc.iProduct, product); | 501 return GetStringDescriptor(desc.iProduct, product); |
| 497 } | 502 } |
| 498 | 503 |
| 499 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { | 504 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { |
| 500 DCHECK(thread_checker_.CalledOnValidThread()); | 505 DCHECK(thread_checker_.CalledOnValidThread()); |
| 501 PlatformUsbDevice device = libusb_get_device(handle_); | 506 PlatformUsbDevice device = libusb_get_device(handle_); |
| 502 libusb_device_descriptor desc; | 507 libusb_device_descriptor desc; |
| 503 | 508 |
| 504 // This is a non-blocking call as libusb has the descriptor in memory. | 509 // This is a non-blocking call as libusb has the descriptor in memory. |
| 505 const int rv = libusb_get_device_descriptor(device, &desc); | 510 const int rv = libusb_get_device_descriptor(device, &desc); |
| 506 if (rv != LIBUSB_SUCCESS) { | 511 if (rv != LIBUSB_SUCCESS) { |
| 507 VLOG(1) << "Failed to read device descriptor: " << ConvertErrorToString(rv); | 512 VLOG(1) << "Failed to read device descriptor: " |
| 513 << ConvertPlatformUsbErrorToString(rv); |
| 508 return false; | 514 return false; |
| 509 } | 515 } |
| 510 | 516 |
| 511 if (desc.iSerialNumber == 0) { | 517 if (desc.iSerialNumber == 0) { |
| 512 return false; | 518 return false; |
| 513 } | 519 } |
| 514 | 520 |
| 515 return GetStringDescriptor(desc.iSerialNumber, serial); | 521 return GetStringDescriptor(desc.iSerialNumber, serial); |
| 516 } | 522 } |
| 517 | 523 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 } | 728 } |
| 723 | 729 |
| 724 // It's OK for this method to return NULL. libusb_submit_transfer will fail if | 730 // It's OK for this method to return NULL. libusb_submit_transfer will fail if |
| 725 // it requires an interface we didn't claim. | 731 // it requires an interface we didn't claim. |
| 726 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); | 732 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); |
| 727 | 733 |
| 728 const int rv = libusb_submit_transfer(handle); | 734 const int rv = libusb_submit_transfer(handle); |
| 729 if (rv == LIBUSB_SUCCESS) { | 735 if (rv == LIBUSB_SUCCESS) { |
| 730 transfers_[handle] = transfer; | 736 transfers_[handle] = transfer; |
| 731 } else { | 737 } else { |
| 732 VLOG(1) << "Failed to submit transfer: " << ConvertErrorToString(rv); | 738 VLOG(1) << "Failed to submit transfer: " |
| 739 << ConvertPlatformUsbErrorToString(rv); |
| 733 transfer.Complete(USB_TRANSFER_ERROR, 0); | 740 transfer.Complete(USB_TRANSFER_ERROR, 0); |
| 734 } | 741 } |
| 735 } | 742 } |
| 736 | 743 |
| 737 void UsbDeviceHandleImpl::InternalClose() { | 744 void UsbDeviceHandleImpl::InternalClose() { |
| 738 DCHECK(thread_checker_.CalledOnValidThread()); | 745 DCHECK(thread_checker_.CalledOnValidThread()); |
| 739 if (!device_) | 746 if (!device_) |
| 740 return; | 747 return; |
| 741 | 748 |
| 742 // Cancel all the transfers. | 749 // Cancel all the transfers. |
| 743 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); | 750 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
| 744 ++it) { | 751 ++it) { |
| 745 // The callback will be called some time later. | 752 // The callback will be called some time later. |
| 746 libusb_cancel_transfer(it->first); | 753 libusb_cancel_transfer(it->first); |
| 747 } | 754 } |
| 748 | 755 |
| 749 // Attempt-release all the interfaces. | 756 // Attempt-release all the interfaces. |
| 750 // It will be retained until the transfer cancellation is finished. | 757 // It will be retained until the transfer cancellation is finished. |
| 751 claimed_interfaces_.clear(); | 758 claimed_interfaces_.clear(); |
| 752 | 759 |
| 753 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 760 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
| 754 // finish. | 761 // finish. |
| 755 device_ = NULL; | 762 device_ = NULL; |
| 756 } | 763 } |
| 757 | 764 |
| 758 } // namespace usb_service | 765 } // namespace device |
| OLD | NEW |