Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Side by Side Diff: device/usb/usb_device_handle_impl.cc

Issue 601073002: Move string descriptor getters from UsbDeviceHandle to UsbDevice. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix function order. Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | device/usb/usb_device_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « device/usb/usb_device_handle_impl.h ('k') | device/usb/usb_device_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698