| 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 |