| 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" |
| 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 "components/usb_service/usb_context.h" | 14 #include "components/usb_service/usb_context.h" |
| 15 #include "components/usb_service/usb_device_impl.h" | 15 #include "components/usb_service/usb_device_impl.h" |
| 16 #include "components/usb_service/usb_error.h" |
| 16 #include "components/usb_service/usb_interface.h" | 17 #include "components/usb_service/usb_interface.h" |
| 17 #include "components/usb_service/usb_service.h" | 18 #include "components/usb_service/usb_service.h" |
| 18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 19 #include "third_party/libusb/src/libusb/libusb.h" | 20 #include "third_party/libusb/src/libusb/libusb.h" |
| 20 | 21 |
| 21 using content::BrowserThread; | 22 using content::BrowserThread; |
| 22 | 23 |
| 23 namespace usb_service { | 24 namespace usb_service { |
| 24 | 25 |
| 25 typedef libusb_device* PlatformUsbDevice; | 26 typedef libusb_device* PlatformUsbDevice; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 : handle_(handle), | 152 : handle_(handle), |
| 152 interface_number_(interface_number), | 153 interface_number_(interface_number), |
| 153 alternate_setting_(0) { | 154 alternate_setting_(0) { |
| 154 } | 155 } |
| 155 | 156 |
| 156 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { | 157 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { |
| 157 libusb_release_interface(handle_->handle(), interface_number_); | 158 libusb_release_interface(handle_->handle(), interface_number_); |
| 158 } | 159 } |
| 159 | 160 |
| 160 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { | 161 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { |
| 161 return libusb_claim_interface(handle_->handle(), interface_number_) == 0; | 162 const int rv = libusb_claim_interface(handle_->handle(), interface_number_); |
| 163 if (rv != LIBUSB_SUCCESS) { |
| 164 LOG(ERROR) << "Failed to claim interface: " << ConvertErrorToString(rv); |
| 165 } |
| 166 return rv == LIBUSB_SUCCESS; |
| 162 } | 167 } |
| 163 | 168 |
| 164 struct UsbDeviceHandleImpl::Transfer { | 169 struct UsbDeviceHandleImpl::Transfer { |
| 165 Transfer(); | 170 Transfer(); |
| 166 ~Transfer(); | 171 ~Transfer(); |
| 167 | 172 |
| 168 UsbTransferType transfer_type; | 173 UsbTransferType transfer_type; |
| 169 scoped_refptr<net::IOBuffer> buffer; | 174 scoped_refptr<net::IOBuffer> buffer; |
| 170 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface; | 175 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface; |
| 171 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; | 176 scoped_refptr<base::MessageLoopProxy> message_loop_proxy; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( | 342 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( |
| 338 const int interface_number, | 343 const int interface_number, |
| 339 const int alternate_setting) { | 344 const int alternate_setting) { |
| 340 DCHECK(thread_checker_.CalledOnValidThread()); | 345 DCHECK(thread_checker_.CalledOnValidThread()); |
| 341 if (!device_) | 346 if (!device_) |
| 342 return false; | 347 return false; |
| 343 if (!ContainsKey(claimed_interfaces_, interface_number)) | 348 if (!ContainsKey(claimed_interfaces_, interface_number)) |
| 344 return false; | 349 return false; |
| 345 const int rv = libusb_set_interface_alt_setting( | 350 const int rv = libusb_set_interface_alt_setting( |
| 346 handle_, interface_number, alternate_setting); | 351 handle_, interface_number, alternate_setting); |
| 347 if (rv == 0) { | 352 if (rv == LIBUSB_SUCCESS) { |
| 348 claimed_interfaces_[interface_number]->set_alternate_setting( | 353 claimed_interfaces_[interface_number]->set_alternate_setting( |
| 349 alternate_setting); | 354 alternate_setting); |
| 350 RefreshEndpointMap(); | 355 RefreshEndpointMap(); |
| 351 return true; | 356 } else { |
| 357 LOG(ERROR) << "Failed to set interface (" << interface_number |
| 358 << ", " << alternate_setting << "): " << ConvertErrorToString(rv); |
| 352 } | 359 } |
| 353 return false; | 360 return rv == LIBUSB_SUCCESS; |
| 354 } | 361 } |
| 355 | 362 |
| 356 bool UsbDeviceHandleImpl::ResetDevice() { | 363 bool UsbDeviceHandleImpl::ResetDevice() { |
| 357 DCHECK(thread_checker_.CalledOnValidThread()); | 364 DCHECK(thread_checker_.CalledOnValidThread()); |
| 358 if (!device_) | 365 if (!device_) |
| 359 return false; | 366 return false; |
| 360 | 367 |
| 361 return libusb_reset_device(handle_) == 0; | 368 const int rv = libusb_reset_device(handle_); |
| 369 if (rv != LIBUSB_SUCCESS) { |
| 370 LOG(ERROR) << "Failed to reset device: " << ConvertErrorToString(rv); |
| 371 } |
| 372 return rv == LIBUSB_SUCCESS; |
| 362 } | 373 } |
| 363 | 374 |
| 364 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { | 375 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { |
| 365 DCHECK(thread_checker_.CalledOnValidThread()); | 376 DCHECK(thread_checker_.CalledOnValidThread()); |
| 366 PlatformUsbDevice device = libusb_get_device(handle_); | 377 PlatformUsbDevice device = libusb_get_device(handle_); |
| 367 libusb_device_descriptor desc; | 378 libusb_device_descriptor desc; |
| 368 | 379 |
| 369 if (libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) | 380 const int rv = libusb_get_device_descriptor(device, &desc); |
| 381 if (rv != LIBUSB_SUCCESS) { |
| 382 LOG(ERROR) << "Failed to read device descriptor: " |
| 383 << ConvertErrorToString(rv); |
| 370 return false; | 384 return false; |
| 385 } |
| 371 | 386 |
| 372 if (desc.iSerialNumber == 0) | 387 if (desc.iSerialNumber == 0) |
| 373 return false; | 388 return false; |
| 374 | 389 |
| 375 // Getting supported language ID. | 390 // Getting supported language ID. |
| 376 uint16 langid[128] = {0}; | 391 uint16 langid[128] = {0}; |
| 377 | 392 |
| 378 int size = | 393 int size = |
| 379 libusb_get_string_descriptor(handle_, | 394 libusb_get_string_descriptor(handle_, |
| 380 0, | 395 0, |
| 381 0, | 396 0, |
| 382 reinterpret_cast<unsigned char*>(&langid[0]), | 397 reinterpret_cast<unsigned char*>(&langid[0]), |
| 383 sizeof(langid)); | 398 sizeof(langid)); |
| 384 if (size < 0) | 399 if (size < 0) { |
| 400 LOG(ERROR) << "Failed to get language IDs: " |
| 401 << ConvertErrorToString(size); |
| 385 return false; | 402 return false; |
| 403 } |
| 386 | 404 |
| 387 int language_count = (size - 2) / 2; | 405 int language_count = (size - 2) / 2; |
| 388 | 406 |
| 389 for (int i = 1; i <= language_count; ++i) { | 407 for (int i = 1; i <= language_count; ++i) { |
| 390 // Get the string using language ID. | 408 // Get the string using language ID. |
| 391 base::char16 text[256] = {0}; | 409 base::char16 text[256] = {0}; |
| 392 size = | 410 size = |
| 393 libusb_get_string_descriptor(handle_, | 411 libusb_get_string_descriptor(handle_, |
| 394 desc.iSerialNumber, | 412 desc.iSerialNumber, |
| 395 langid[i], | 413 langid[i], |
| 396 reinterpret_cast<unsigned char*>(&text[0]), | 414 reinterpret_cast<unsigned char*>(&text[0]), |
| 397 sizeof(text)); | 415 sizeof(text)); |
| 416 if (size < 0) { |
| 417 LOG(ERROR) << "Failed to get serial number (langid " << langid[i] << "): " |
| 418 << ConvertErrorToString(size); |
| 419 continue; |
| 420 } |
| 398 if (size <= 2) | 421 if (size <= 2) |
| 399 continue; | 422 continue; |
| 400 if ((text[0] >> 8) != LIBUSB_DT_STRING) | 423 if ((text[0] >> 8) != LIBUSB_DT_STRING) |
| 401 continue; | 424 continue; |
| 402 if ((text[0] & 255) > size) | 425 if ((text[0] & 255) > size) |
| 403 continue; | 426 continue; |
| 404 | 427 |
| 405 size = size / 2 - 1; | 428 size = size / 2 - 1; |
| 406 *serial = base::string16(text + 1, size); | 429 *serial = base::string16(text + 1, size); |
| 407 return true; | 430 return true; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 619 transfer.transfer_type = transfer_type; | 642 transfer.transfer_type = transfer_type; |
| 620 transfer.buffer = buffer; | 643 transfer.buffer = buffer; |
| 621 transfer.length = length; | 644 transfer.length = length; |
| 622 transfer.callback = callback; | 645 transfer.callback = callback; |
| 623 transfer.message_loop_proxy = message_loop_proxy; | 646 transfer.message_loop_proxy = message_loop_proxy; |
| 624 | 647 |
| 625 // It's OK for this method to return NULL. libusb_submit_transfer will fail if | 648 // It's OK for this method to return NULL. libusb_submit_transfer will fail if |
| 626 // it requires an interface we didn't claim. | 649 // it requires an interface we didn't claim. |
| 627 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); | 650 transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); |
| 628 | 651 |
| 629 if (libusb_submit_transfer(handle) == LIBUSB_SUCCESS) { | 652 const int rv = libusb_submit_transfer(handle); |
| 653 if (rv == LIBUSB_SUCCESS) { |
| 630 transfers_[handle] = transfer; | 654 transfers_[handle] = transfer; |
| 631 } else { | 655 } else { |
| 656 LOG(ERROR) << "Failed to submit transfer: " << ConvertErrorToString(rv); |
| 632 message_loop_proxy->PostTask( | 657 message_loop_proxy->PostTask( |
| 633 FROM_HERE, | 658 FROM_HERE, |
| 634 base::Bind( | 659 base::Bind( |
| 635 callback, USB_TRANSFER_ERROR, make_scoped_refptr(buffer), 0)); | 660 callback, USB_TRANSFER_ERROR, make_scoped_refptr(buffer), 0)); |
| 636 } | 661 } |
| 637 } | 662 } |
| 638 | 663 |
| 639 void UsbDeviceHandleImpl::InternalClose() { | 664 void UsbDeviceHandleImpl::InternalClose() { |
| 640 DCHECK(thread_checker_.CalledOnValidThread()); | 665 DCHECK(thread_checker_.CalledOnValidThread()); |
| 641 if (!device_) | 666 if (!device_) |
| 642 return; | 667 return; |
| 643 | 668 |
| 644 // Cancel all the transfers. | 669 // Cancel all the transfers. |
| 645 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); | 670 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
| 646 ++it) { | 671 ++it) { |
| 647 // The callback will be called some time later. | 672 // The callback will be called some time later. |
| 648 libusb_cancel_transfer(it->first); | 673 libusb_cancel_transfer(it->first); |
| 649 } | 674 } |
| 650 | 675 |
| 651 // Attempt-release all the interfaces. | 676 // Attempt-release all the interfaces. |
| 652 // It will be retained until the transfer cancellation is finished. | 677 // It will be retained until the transfer cancellation is finished. |
| 653 claimed_interfaces_.clear(); | 678 claimed_interfaces_.clear(); |
| 654 | 679 |
| 655 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 680 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
| 656 // finish. | 681 // finish. |
| 657 device_ = NULL; | 682 device_ = NULL; |
| 658 } | 683 } |
| 659 | 684 |
| 660 } // namespace usb_service | 685 } // namespace usb_service |
| OLD | NEW |