| 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 "device/usb/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" |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { | 204 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { |
| 205 return static_cast<UsbDevice*>(device_); | 205 return static_cast<UsbDevice*>(device_); |
| 206 } | 206 } |
| 207 | 207 |
| 208 void UsbDeviceHandleImpl::Close() { | 208 void UsbDeviceHandleImpl::Close() { |
| 209 DCHECK(thread_checker_.CalledOnValidThread()); | 209 DCHECK(thread_checker_.CalledOnValidThread()); |
| 210 if (device_) | 210 if (device_) |
| 211 device_->Close(this); | 211 device_->Close(this); |
| 212 } | 212 } |
| 213 | 213 |
| 214 /* static */ | |
| 215 void LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback( | |
| 216 PlatformUsbTransferHandle transfer) { | |
| 217 UsbDeviceHandleImpl* device_handle = | |
| 218 reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); | |
| 219 device_handle->task_runner_->PostTask( | |
| 220 FROM_HERE, | |
| 221 base::Bind( | |
| 222 &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer)); | |
| 223 } | |
| 224 | |
| 225 void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) { | |
| 226 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; | |
| 227 | |
| 228 Transfer transfer = transfers_[handle]; | |
| 229 transfers_.erase(handle); | |
| 230 | |
| 231 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; | |
| 232 size_t actual_length = | |
| 233 static_cast<size_t>(std::max(handle->actual_length, 0)); | |
| 234 | |
| 235 DCHECK(transfer.length >= actual_length) | |
| 236 << "data too big for our buffer (libusb failure?)"; | |
| 237 | |
| 238 switch (transfer.transfer_type) { | |
| 239 case USB_TRANSFER_CONTROL: | |
| 240 // If the transfer is a control transfer we do not expose the control | |
| 241 // setup header to the caller. This logic strips off the header if | |
| 242 // present before invoking the callback provided with the transfer. | |
| 243 if (actual_length > 0) { | |
| 244 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) | |
| 245 << "buffer was not correctly set: too small for the control header"; | |
| 246 | |
| 247 if (transfer.length >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) { | |
| 248 // If the payload is zero bytes long, pad out the allocated buffer | |
| 249 // size to one byte so that an IOBuffer of that size can be allocated. | |
| 250 scoped_refptr<net::IOBuffer> resized_buffer = | |
| 251 new net::IOBuffer(static_cast<int>( | |
| 252 std::max(actual_length, static_cast<size_t>(1)))); | |
| 253 memcpy(resized_buffer->data(), | |
| 254 transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, | |
| 255 actual_length); | |
| 256 transfer.buffer = resized_buffer; | |
| 257 } | |
| 258 } | |
| 259 break; | |
| 260 | |
| 261 case USB_TRANSFER_ISOCHRONOUS: | |
| 262 // Isochronous replies might carry data in the different isoc packets even | |
| 263 // if the transfer actual_data value is zero. Furthermore, not all of the | |
| 264 // received packets might contain data, so we need to calculate how many | |
| 265 // data bytes we are effectively providing and pack the results. | |
| 266 if (actual_length == 0) { | |
| 267 size_t packet_buffer_start = 0; | |
| 268 for (int i = 0; i < handle->num_iso_packets; ++i) { | |
| 269 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; | |
| 270 if (packet->actual_length > 0) { | |
| 271 // We don't need to copy as long as all packets until now provide | |
| 272 // all the data the packet can hold. | |
| 273 if (actual_length < packet_buffer_start) { | |
| 274 CHECK(packet_buffer_start + packet->actual_length <= | |
| 275 transfer.length); | |
| 276 memmove(transfer.buffer->data() + actual_length, | |
| 277 transfer.buffer->data() + packet_buffer_start, | |
| 278 packet->actual_length); | |
| 279 } | |
| 280 actual_length += packet->actual_length; | |
| 281 } | |
| 282 | |
| 283 packet_buffer_start += packet->length; | |
| 284 } | |
| 285 } | |
| 286 break; | |
| 287 | |
| 288 case USB_TRANSFER_BULK: | |
| 289 case USB_TRANSFER_INTERRUPT: | |
| 290 break; | |
| 291 | |
| 292 default: | |
| 293 NOTREACHED() << "Invalid usb transfer type"; | |
| 294 break; | |
| 295 } | |
| 296 | |
| 297 transfer.Complete(ConvertTransferStatus(handle->status), actual_length); | |
| 298 libusb_free_transfer(handle); | |
| 299 | |
| 300 // Must release interface first before actually delete this. | |
| 301 transfer.claimed_interface = NULL; | |
| 302 } | |
| 303 | |
| 304 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { | 214 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { |
| 305 DCHECK(thread_checker_.CalledOnValidThread()); | 215 DCHECK(thread_checker_.CalledOnValidThread()); |
| 306 if (!device_) | 216 if (!device_) |
| 307 return false; | 217 return false; |
| 308 if (ContainsKey(claimed_interfaces_, interface_number)) | 218 if (ContainsKey(claimed_interfaces_, interface_number)) |
| 309 return true; | 219 return true; |
| 310 | 220 |
| 311 scoped_refptr<InterfaceClaimer> claimer = | 221 scoped_refptr<InterfaceClaimer> claimer = |
| 312 new InterfaceClaimer(this, interface_number); | 222 new InterfaceClaimer(this, interface_number); |
| 313 | 223 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 return false; | 278 return false; |
| 369 | 279 |
| 370 const int rv = libusb_reset_device(handle_); | 280 const int rv = libusb_reset_device(handle_); |
| 371 if (rv != LIBUSB_SUCCESS) { | 281 if (rv != LIBUSB_SUCCESS) { |
| 372 VLOG(1) << "Failed to reset device: " | 282 VLOG(1) << "Failed to reset device: " |
| 373 << ConvertPlatformUsbErrorToString(rv); | 283 << ConvertPlatformUsbErrorToString(rv); |
| 374 } | 284 } |
| 375 return rv == LIBUSB_SUCCESS; | 285 return rv == LIBUSB_SUCCESS; |
| 376 } | 286 } |
| 377 | 287 |
| 378 bool UsbDeviceHandleImpl::GetSupportedLanguages() { | |
| 379 if (!languages_.empty()) { | |
| 380 return true; | |
| 381 } | |
| 382 | |
| 383 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). | |
| 384 uint16 languages[128]; | |
| 385 int size = libusb_get_string_descriptor( | |
| 386 handle_, | |
| 387 0, | |
| 388 0, | |
| 389 reinterpret_cast<unsigned char*>(&languages[0]), | |
| 390 sizeof(languages)); | |
| 391 if (size < 0) { | |
| 392 VLOG(1) << "Failed to get list of supported languages: " | |
| 393 << ConvertPlatformUsbErrorToString(size); | |
| 394 return false; | |
| 395 } else if (size < 2) { | |
| 396 VLOG(1) << "String descriptor zero has no header."; | |
| 397 return false; | |
| 398 // The first 2 bytes of the descriptor are the total length and type tag. | |
| 399 } else if ((languages[0] & 0xff) != size) { | |
| 400 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) | |
| 401 << " != " << size; | |
| 402 return false; | |
| 403 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { | |
| 404 VLOG(1) << "String descriptor zero is not a string descriptor."; | |
| 405 return false; | |
| 406 } | |
| 407 | |
| 408 languages_.assign(languages[1], languages[(size - 2) / 2]); | |
| 409 return true; | |
| 410 } | |
| 411 | |
| 412 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, | 288 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, |
| 413 base::string16* string) { | 289 base::string16* string) { |
| 414 if (!GetSupportedLanguages()) { | 290 if (!GetSupportedLanguages()) { |
| 415 return false; | 291 return false; |
| 416 } | 292 } |
| 417 | 293 |
| 418 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); | 294 std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); |
| 419 if (it != strings_.end()) { | 295 if (it != strings_.end()) { |
| 420 *string = it->second; | 296 *string = it->second; |
| 421 return true; | 297 return true; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 452 } | 328 } |
| 453 | 329 |
| 454 *string = base::string16(text + 1, (size - 2) / 2); | 330 *string = base::string16(text + 1, (size - 2) / 2); |
| 455 strings_[string_id] = *string; | 331 strings_[string_id] = *string; |
| 456 return true; | 332 return true; |
| 457 } | 333 } |
| 458 | 334 |
| 459 return false; | 335 return false; |
| 460 } | 336 } |
| 461 | 337 |
| 462 bool UsbDeviceHandleImpl::GetManufacturer(base::string16* manufacturer) { | |
| 463 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 464 PlatformUsbDevice device = libusb_get_device(handle_); | |
| 465 libusb_device_descriptor desc; | |
| 466 | |
| 467 // This is a non-blocking call as libusb has the descriptor in memory. | |
| 468 const int rv = libusb_get_device_descriptor(device, &desc); | |
| 469 if (rv != LIBUSB_SUCCESS) { | |
| 470 VLOG(1) << "Failed to read device descriptor: " | |
| 471 << ConvertPlatformUsbErrorToString(rv); | |
| 472 return false; | |
| 473 } | |
| 474 | |
| 475 if (desc.iManufacturer == 0) { | |
| 476 return false; | |
| 477 } | |
| 478 | |
| 479 return GetStringDescriptor(desc.iManufacturer, manufacturer); | |
| 480 } | |
| 481 | |
| 482 bool UsbDeviceHandleImpl::GetProduct(base::string16* product) { | |
| 483 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 484 PlatformUsbDevice device = libusb_get_device(handle_); | |
| 485 libusb_device_descriptor desc; | |
| 486 | |
| 487 // This is a non-blocking call as libusb has the descriptor in memory. | |
| 488 const int rv = libusb_get_device_descriptor(device, &desc); | |
| 489 if (rv != LIBUSB_SUCCESS) { | |
| 490 VLOG(1) << "Failed to read device descriptor: " | |
| 491 << ConvertPlatformUsbErrorToString(rv); | |
| 492 return false; | |
| 493 } | |
| 494 | |
| 495 if (desc.iProduct == 0) { | |
| 496 return false; | |
| 497 } | |
| 498 | |
| 499 return GetStringDescriptor(desc.iProduct, product); | |
| 500 } | |
| 501 | |
| 502 bool UsbDeviceHandleImpl::GetSerial(base::string16* serial) { | |
| 503 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 504 PlatformUsbDevice device = libusb_get_device(handle_); | |
| 505 libusb_device_descriptor desc; | |
| 506 | |
| 507 // This is a non-blocking call as libusb has the descriptor in memory. | |
| 508 const int rv = libusb_get_device_descriptor(device, &desc); | |
| 509 if (rv != LIBUSB_SUCCESS) { | |
| 510 VLOG(1) << "Failed to read device descriptor: " | |
| 511 << ConvertPlatformUsbErrorToString(rv); | |
| 512 return false; | |
| 513 } | |
| 514 | |
| 515 if (desc.iSerialNumber == 0) { | |
| 516 return false; | |
| 517 } | |
| 518 | |
| 519 return GetStringDescriptor(desc.iSerialNumber, serial); | |
| 520 } | |
| 521 | |
| 522 void UsbDeviceHandleImpl::ControlTransfer( | 338 void UsbDeviceHandleImpl::ControlTransfer( |
| 523 const UsbEndpointDirection direction, | 339 const UsbEndpointDirection direction, |
| 524 const TransferRequestType request_type, | 340 const TransferRequestType request_type, |
| 525 const TransferRecipient recipient, | 341 const TransferRecipient recipient, |
| 526 const uint8 request, | 342 const uint8 request, |
| 527 const uint16 value, | 343 const uint16 value, |
| 528 const uint16 index, | 344 const uint16 index, |
| 529 net::IOBuffer* buffer, | 345 net::IOBuffer* buffer, |
| 530 const size_t length, | 346 const size_t length, |
| 531 const unsigned int timeout, | 347 const unsigned int timeout, |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 const int rv = libusb_submit_transfer(handle); | 558 const int rv = libusb_submit_transfer(handle); |
| 743 if (rv == LIBUSB_SUCCESS) { | 559 if (rv == LIBUSB_SUCCESS) { |
| 744 transfers_[handle] = transfer; | 560 transfers_[handle] = transfer; |
| 745 } else { | 561 } else { |
| 746 VLOG(1) << "Failed to submit transfer: " | 562 VLOG(1) << "Failed to submit transfer: " |
| 747 << ConvertPlatformUsbErrorToString(rv); | 563 << ConvertPlatformUsbErrorToString(rv); |
| 748 transfer.Complete(USB_TRANSFER_ERROR, 0); | 564 transfer.Complete(USB_TRANSFER_ERROR, 0); |
| 749 } | 565 } |
| 750 } | 566 } |
| 751 | 567 |
| 568 /* static */ |
| 569 void LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback( |
| 570 PlatformUsbTransferHandle transfer) { |
| 571 UsbDeviceHandleImpl* device_handle = |
| 572 reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); |
| 573 device_handle->task_runner_->PostTask( |
| 574 FROM_HERE, |
| 575 base::Bind( |
| 576 &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer)); |
| 577 } |
| 578 |
| 579 void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) { |
| 580 DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; |
| 581 |
| 582 Transfer transfer = transfers_[handle]; |
| 583 transfers_.erase(handle); |
| 584 |
| 585 DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; |
| 586 size_t actual_length = |
| 587 static_cast<size_t>(std::max(handle->actual_length, 0)); |
| 588 |
| 589 DCHECK(transfer.length >= actual_length) |
| 590 << "data too big for our buffer (libusb failure?)"; |
| 591 |
| 592 switch (transfer.transfer_type) { |
| 593 case USB_TRANSFER_CONTROL: |
| 594 // If the transfer is a control transfer we do not expose the control |
| 595 // setup header to the caller. This logic strips off the header if |
| 596 // present before invoking the callback provided with the transfer. |
| 597 if (actual_length > 0) { |
| 598 CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) |
| 599 << "buffer was not correctly set: too small for the control header"; |
| 600 |
| 601 if (transfer.length >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) { |
| 602 // If the payload is zero bytes long, pad out the allocated buffer |
| 603 // size to one byte so that an IOBuffer of that size can be allocated. |
| 604 scoped_refptr<net::IOBuffer> resized_buffer = |
| 605 new net::IOBuffer(static_cast<int>( |
| 606 std::max(actual_length, static_cast<size_t>(1)))); |
| 607 memcpy(resized_buffer->data(), |
| 608 transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, |
| 609 actual_length); |
| 610 transfer.buffer = resized_buffer; |
| 611 } |
| 612 } |
| 613 break; |
| 614 |
| 615 case USB_TRANSFER_ISOCHRONOUS: |
| 616 // Isochronous replies might carry data in the different isoc packets even |
| 617 // if the transfer actual_data value is zero. Furthermore, not all of the |
| 618 // received packets might contain data, so we need to calculate how many |
| 619 // data bytes we are effectively providing and pack the results. |
| 620 if (actual_length == 0) { |
| 621 size_t packet_buffer_start = 0; |
| 622 for (int i = 0; i < handle->num_iso_packets; ++i) { |
| 623 PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; |
| 624 if (packet->actual_length > 0) { |
| 625 // We don't need to copy as long as all packets until now provide |
| 626 // all the data the packet can hold. |
| 627 if (actual_length < packet_buffer_start) { |
| 628 CHECK(packet_buffer_start + packet->actual_length <= |
| 629 transfer.length); |
| 630 memmove(transfer.buffer->data() + actual_length, |
| 631 transfer.buffer->data() + packet_buffer_start, |
| 632 packet->actual_length); |
| 633 } |
| 634 actual_length += packet->actual_length; |
| 635 } |
| 636 |
| 637 packet_buffer_start += packet->length; |
| 638 } |
| 639 } |
| 640 break; |
| 641 |
| 642 case USB_TRANSFER_BULK: |
| 643 case USB_TRANSFER_INTERRUPT: |
| 644 break; |
| 645 |
| 646 default: |
| 647 NOTREACHED() << "Invalid usb transfer type"; |
| 648 break; |
| 649 } |
| 650 |
| 651 transfer.Complete(ConvertTransferStatus(handle->status), actual_length); |
| 652 libusb_free_transfer(handle); |
| 653 |
| 654 // Must release interface first before actually delete this. |
| 655 transfer.claimed_interface = NULL; |
| 656 } |
| 657 |
| 658 bool UsbDeviceHandleImpl::GetSupportedLanguages() { |
| 659 if (!languages_.empty()) { |
| 660 return true; |
| 661 } |
| 662 |
| 663 // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). |
| 664 uint16 languages[128]; |
| 665 int size = libusb_get_string_descriptor( |
| 666 handle_, |
| 667 0, |
| 668 0, |
| 669 reinterpret_cast<unsigned char*>(&languages[0]), |
| 670 sizeof(languages)); |
| 671 if (size < 0) { |
| 672 VLOG(1) << "Failed to get list of supported languages: " |
| 673 << ConvertPlatformUsbErrorToString(size); |
| 674 return false; |
| 675 } else if (size < 2) { |
| 676 VLOG(1) << "String descriptor zero has no header."; |
| 677 return false; |
| 678 // The first 2 bytes of the descriptor are the total length and type tag. |
| 679 } else if ((languages[0] & 0xff) != size) { |
| 680 VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) |
| 681 << " != " << size; |
| 682 return false; |
| 683 } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { |
| 684 VLOG(1) << "String descriptor zero is not a string descriptor."; |
| 685 return false; |
| 686 } |
| 687 |
| 688 languages_.assign(languages[1], languages[(size - 2) / 2]); |
| 689 return true; |
| 690 } |
| 691 |
| 752 void UsbDeviceHandleImpl::InternalClose() { | 692 void UsbDeviceHandleImpl::InternalClose() { |
| 753 DCHECK(thread_checker_.CalledOnValidThread()); | 693 DCHECK(thread_checker_.CalledOnValidThread()); |
| 754 if (!device_) | 694 if (!device_) |
| 755 return; | 695 return; |
| 756 | 696 |
| 757 // Cancel all the transfers. | 697 // Cancel all the transfers. |
| 758 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); | 698 for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); |
| 759 ++it) { | 699 ++it) { |
| 760 // The callback will be called some time later. | 700 // The callback will be called some time later. |
| 761 libusb_cancel_transfer(it->first); | 701 libusb_cancel_transfer(it->first); |
| 762 } | 702 } |
| 763 | 703 |
| 764 // Attempt-release all the interfaces. | 704 // Attempt-release all the interfaces. |
| 765 // It will be retained until the transfer cancellation is finished. | 705 // It will be retained until the transfer cancellation is finished. |
| 766 claimed_interfaces_.clear(); | 706 claimed_interfaces_.clear(); |
| 767 | 707 |
| 768 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to | 708 // Cannot close device handle here. Need to wait for libusb_cancel_transfer to |
| 769 // finish. | 709 // finish. |
| 770 device_ = NULL; | 710 device_ = NULL; |
| 771 } | 711 } |
| 772 | 712 |
| 773 } // namespace device | 713 } // namespace device |
| OLD | NEW |