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 |