Home | History | Annotate | Download | only in usb
      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
      3 // found in the LICENSE file.
      4 
      5 #include "device/usb/usb_device_handle_impl.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/bind.h"
     11 #include "base/location.h"
     12 #include "base/single_thread_task_runner.h"
     13 #include "base/stl_util.h"
     14 #include "base/strings/string16.h"
     15 #include "base/synchronization/lock.h"
     16 #include "base/thread_task_runner_handle.h"
     17 #include "device/usb/usb_context.h"
     18 #include "device/usb/usb_descriptors.h"
     19 #include "device/usb/usb_device_impl.h"
     20 #include "device/usb/usb_error.h"
     21 #include "device/usb/usb_service.h"
     22 #include "third_party/libusb/src/libusb/libusb.h"
     23 
     24 namespace device {
     25 
     26 typedef libusb_device* PlatformUsbDevice;
     27 
     28 void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
     29 
     30 namespace {
     31 
     32 static uint8 ConvertTransferDirection(const UsbEndpointDirection direction) {
     33   switch (direction) {
     34     case USB_DIRECTION_INBOUND:
     35       return LIBUSB_ENDPOINT_IN;
     36     case USB_DIRECTION_OUTBOUND:
     37       return LIBUSB_ENDPOINT_OUT;
     38     default:
     39       NOTREACHED();
     40       return LIBUSB_ENDPOINT_IN;
     41   }
     42 }
     43 
     44 static uint8 CreateRequestType(
     45     const UsbEndpointDirection direction,
     46     const UsbDeviceHandle::TransferRequestType request_type,
     47     const UsbDeviceHandle::TransferRecipient recipient) {
     48   uint8 result = ConvertTransferDirection(direction);
     49 
     50   switch (request_type) {
     51     case UsbDeviceHandle::STANDARD:
     52       result |= LIBUSB_REQUEST_TYPE_STANDARD;
     53       break;
     54     case UsbDeviceHandle::CLASS:
     55       result |= LIBUSB_REQUEST_TYPE_CLASS;
     56       break;
     57     case UsbDeviceHandle::VENDOR:
     58       result |= LIBUSB_REQUEST_TYPE_VENDOR;
     59       break;
     60     case UsbDeviceHandle::RESERVED:
     61       result |= LIBUSB_REQUEST_TYPE_RESERVED;
     62       break;
     63   }
     64 
     65   switch (recipient) {
     66     case UsbDeviceHandle::DEVICE:
     67       result |= LIBUSB_RECIPIENT_DEVICE;
     68       break;
     69     case UsbDeviceHandle::INTERFACE:
     70       result |= LIBUSB_RECIPIENT_INTERFACE;
     71       break;
     72     case UsbDeviceHandle::ENDPOINT:
     73       result |= LIBUSB_RECIPIENT_ENDPOINT;
     74       break;
     75     case UsbDeviceHandle::OTHER:
     76       result |= LIBUSB_RECIPIENT_OTHER;
     77       break;
     78   }
     79 
     80   return result;
     81 }
     82 
     83 static UsbTransferStatus ConvertTransferStatus(
     84     const libusb_transfer_status status) {
     85   switch (status) {
     86     case LIBUSB_TRANSFER_COMPLETED:
     87       return USB_TRANSFER_COMPLETED;
     88     case LIBUSB_TRANSFER_ERROR:
     89       return USB_TRANSFER_ERROR;
     90     case LIBUSB_TRANSFER_TIMED_OUT:
     91       return USB_TRANSFER_TIMEOUT;
     92     case LIBUSB_TRANSFER_STALL:
     93       return USB_TRANSFER_STALLED;
     94     case LIBUSB_TRANSFER_NO_DEVICE:
     95       return USB_TRANSFER_DISCONNECT;
     96     case LIBUSB_TRANSFER_OVERFLOW:
     97       return USB_TRANSFER_OVERFLOW;
     98     case LIBUSB_TRANSFER_CANCELLED:
     99       return USB_TRANSFER_CANCELLED;
    100     default:
    101       NOTREACHED();
    102       return USB_TRANSFER_ERROR;
    103   }
    104 }
    105 
    106 }  // namespace
    107 
    108 class UsbDeviceHandleImpl::InterfaceClaimer
    109     : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> {
    110  public:
    111   InterfaceClaimer(const scoped_refptr<UsbDeviceHandleImpl> handle,
    112                    const int interface_number);
    113 
    114   bool Claim() const;
    115 
    116   int alternate_setting() const { return alternate_setting_; }
    117   void set_alternate_setting(const int alternate_setting) {
    118     alternate_setting_ = alternate_setting;
    119   }
    120 
    121  private:
    122   friend class UsbDevice;
    123   friend class base::RefCountedThreadSafe<InterfaceClaimer>;
    124   ~InterfaceClaimer();
    125 
    126   const scoped_refptr<UsbDeviceHandleImpl> handle_;
    127   const int interface_number_;
    128   int alternate_setting_;
    129 
    130   DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer);
    131 };
    132 
    133 UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
    134     const scoped_refptr<UsbDeviceHandleImpl> handle,
    135     const int interface_number)
    136     : handle_(handle),
    137       interface_number_(interface_number),
    138       alternate_setting_(0) {
    139 }
    140 
    141 UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
    142   libusb_release_interface(handle_->handle(), interface_number_);
    143 }
    144 
    145 bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const {
    146   const int rv = libusb_claim_interface(handle_->handle(), interface_number_);
    147   if (rv != LIBUSB_SUCCESS) {
    148     VLOG(1) << "Failed to claim interface: "
    149             << ConvertPlatformUsbErrorToString(rv);
    150   }
    151   return rv == LIBUSB_SUCCESS;
    152 }
    153 
    154 struct UsbDeviceHandleImpl::Transfer {
    155   Transfer();
    156   ~Transfer();
    157 
    158   void Complete(UsbTransferStatus status, size_t bytes_transferred);
    159 
    160   UsbTransferType transfer_type;
    161   scoped_refptr<net::IOBuffer> buffer;
    162   scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface;
    163   scoped_refptr<base::SingleThreadTaskRunner> task_runner;
    164   size_t length;
    165   UsbTransferCallback callback;
    166 };
    167 
    168 UsbDeviceHandleImpl::Transfer::Transfer()
    169     : transfer_type(USB_TRANSFER_CONTROL), length(0) {
    170 }
    171 
    172 UsbDeviceHandleImpl::Transfer::~Transfer() {
    173 }
    174 
    175 void UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status,
    176                                              size_t bytes_transferred) {
    177   if (task_runner->RunsTasksOnCurrentThread()) {
    178     callback.Run(status, buffer, bytes_transferred);
    179   } else {
    180     task_runner->PostTask(
    181         FROM_HERE, base::Bind(callback, status, buffer, bytes_transferred));
    182   }
    183 }
    184 
    185 UsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context,
    186                                          UsbDeviceImpl* device,
    187                                          PlatformUsbDeviceHandle handle,
    188                                          const UsbConfigDescriptor& config)
    189     : device_(device),
    190       handle_(handle),
    191       config_(config),
    192       context_(context),
    193       task_runner_(base::ThreadTaskRunnerHandle::Get()) {
    194   DCHECK(handle) << "Cannot create device with NULL handle.";
    195 }
    196 
    197 UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
    198   DCHECK(thread_checker_.CalledOnValidThread());
    199 
    200   libusb_close(handle_);
    201   handle_ = NULL;
    202 }
    203 
    204 scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
    205   return static_cast<UsbDevice*>(device_);
    206 }
    207 
    208 void UsbDeviceHandleImpl::Close() {
    209   DCHECK(thread_checker_.CalledOnValidThread());
    210   if (device_)
    211     device_->Close(this);
    212 }
    213 
    214 bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) {
    215   DCHECK(thread_checker_.CalledOnValidThread());
    216   if (!device_)
    217     return false;
    218   if (ContainsKey(claimed_interfaces_, interface_number))
    219     return true;
    220 
    221   scoped_refptr<InterfaceClaimer> claimer =
    222       new InterfaceClaimer(this, interface_number);
    223 
    224   if (claimer->Claim()) {
    225     claimed_interfaces_[interface_number] = claimer;
    226     RefreshEndpointMap();
    227     return true;
    228   }
    229   return false;
    230 }
    231 
    232 bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) {
    233   DCHECK(thread_checker_.CalledOnValidThread());
    234   if (!device_)
    235     return false;
    236   if (!ContainsKey(claimed_interfaces_, interface_number))
    237     return false;
    238 
    239   // Cancel all the transfers on that interface.
    240   InterfaceClaimer* interface_claimer =
    241       claimed_interfaces_[interface_number].get();
    242   for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end();
    243        ++it) {
    244     if (it->second.claimed_interface.get() == interface_claimer)
    245       libusb_cancel_transfer(it->first);
    246   }
    247   claimed_interfaces_.erase(interface_number);
    248 
    249   RefreshEndpointMap();
    250   return true;
    251 }
    252 
    253 bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
    254     const int interface_number,
    255     const int alternate_setting) {
    256   DCHECK(thread_checker_.CalledOnValidThread());
    257   if (!device_)
    258     return false;
    259   if (!ContainsKey(claimed_interfaces_, interface_number))
    260     return false;
    261   const int rv = libusb_set_interface_alt_setting(
    262       handle_, interface_number, alternate_setting);
    263   if (rv == LIBUSB_SUCCESS) {
    264     claimed_interfaces_[interface_number]->set_alternate_setting(
    265         alternate_setting);
    266     RefreshEndpointMap();
    267   } else {
    268     VLOG(1) << "Failed to set interface (" << interface_number << ", "
    269             << alternate_setting
    270             << "): " << ConvertPlatformUsbErrorToString(rv);
    271   }
    272   return rv == LIBUSB_SUCCESS;
    273 }
    274 
    275 bool UsbDeviceHandleImpl::ResetDevice() {
    276   DCHECK(thread_checker_.CalledOnValidThread());
    277   if (!device_)
    278     return false;
    279 
    280   const int rv = libusb_reset_device(handle_);
    281   if (rv != LIBUSB_SUCCESS) {
    282     VLOG(1) << "Failed to reset device: "
    283             << ConvertPlatformUsbErrorToString(rv);
    284   }
    285   return rv == LIBUSB_SUCCESS;
    286 }
    287 
    288 bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id,
    289                                               base::string16* string) {
    290   if (!GetSupportedLanguages()) {
    291     return false;
    292   }
    293 
    294   std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id);
    295   if (it != strings_.end()) {
    296     *string = it->second;
    297     return true;
    298   }
    299 
    300   for (size_t i = 0; i < languages_.size(); ++i) {
    301     // Get the string using language ID.
    302     uint16 language_id = languages_[i];
    303     // The 1-byte length field limits the descriptor to 256-bytes (128 char16s).
    304     base::char16 text[128];
    305     int size =
    306         libusb_get_string_descriptor(handle_,
    307                                      string_id,
    308                                      language_id,
    309                                      reinterpret_cast<unsigned char*>(&text[0]),
    310                                      sizeof(text));
    311     if (size < 0) {
    312       VLOG(1) << "Failed to get string descriptor " << string_id << " (langid "
    313               << language_id << "): " << ConvertPlatformUsbErrorToString(size);
    314       continue;
    315     } else if (size < 2) {
    316       VLOG(1) << "String descriptor " << string_id << " (langid " << language_id
    317               << ") has no header.";
    318       continue;
    319       // The first 2 bytes of the descriptor are the total length and type tag.
    320     } else if ((text[0] & 0xff) != size) {
    321       VLOG(1) << "String descriptor " << string_id << " (langid " << language_id
    322               << ") size mismatch: " << (text[0] & 0xff) << " != " << size;
    323       continue;
    324     } else if ((text[0] >> 8) != LIBUSB_DT_STRING) {
    325       VLOG(1) << "String descriptor " << string_id << " (langid " << language_id
    326               << ") is not a string descriptor.";
    327       continue;
    328     }
    329 
    330     *string = base::string16(text + 1, (size - 2) / 2);
    331     strings_[string_id] = *string;
    332     return true;
    333   }
    334 
    335   return false;
    336 }
    337 
    338 void UsbDeviceHandleImpl::ControlTransfer(
    339     const UsbEndpointDirection direction,
    340     const TransferRequestType request_type,
    341     const TransferRecipient recipient,
    342     const uint8 request,
    343     const uint16 value,
    344     const uint16 index,
    345     net::IOBuffer* buffer,
    346     const size_t length,
    347     const unsigned int timeout,
    348     const UsbTransferCallback& callback) {
    349   if (!device_) {
    350     callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
    351     return;
    352   }
    353 
    354   const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length;
    355   scoped_refptr<net::IOBuffer> resized_buffer(
    356       new net::IOBufferWithSize(static_cast<int>(resized_length)));
    357   if (!resized_buffer.get()) {
    358     callback.Run(USB_TRANSFER_ERROR, buffer, 0);
    359     return;
    360   }
    361   memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE,
    362          buffer->data(),
    363          static_cast<int>(length));
    364 
    365   PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
    366   const uint8 converted_type =
    367       CreateRequestType(direction, request_type, recipient);
    368   libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()),
    369                             converted_type,
    370                             request,
    371                             value,
    372                             index,
    373                             static_cast<int16>(length));
    374   libusb_fill_control_transfer(transfer,
    375                                handle_,
    376                                reinterpret_cast<uint8*>(resized_buffer->data()),
    377                                &UsbDeviceHandleImpl::PlatformTransferCallback,
    378                                this,
    379                                timeout);
    380 
    381   PostOrSubmitTransfer(transfer,
    382                        USB_TRANSFER_CONTROL,
    383                        resized_buffer.get(),
    384                        resized_length,
    385                        callback);
    386 }
    387 
    388 void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction,
    389                                        const uint8 endpoint,
    390                                        net::IOBuffer* buffer,
    391                                        const size_t length,
    392                                        const unsigned int timeout,
    393                                        const UsbTransferCallback& callback) {
    394   if (!device_) {
    395     callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
    396     return;
    397   }
    398 
    399   PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
    400   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
    401   libusb_fill_bulk_transfer(transfer,
    402                             handle_,
    403                             new_endpoint,
    404                             reinterpret_cast<uint8*>(buffer->data()),
    405                             static_cast<int>(length),
    406                             &UsbDeviceHandleImpl::PlatformTransferCallback,
    407                             this,
    408                             timeout);
    409 
    410   PostOrSubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback);
    411 }
    412 
    413 void UsbDeviceHandleImpl::InterruptTransfer(
    414     const UsbEndpointDirection direction,
    415     const uint8 endpoint,
    416     net::IOBuffer* buffer,
    417     const size_t length,
    418     const unsigned int timeout,
    419     const UsbTransferCallback& callback) {
    420   if (!device_) {
    421     callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
    422     return;
    423   }
    424 
    425   PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0);
    426   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
    427   libusb_fill_interrupt_transfer(transfer,
    428                                  handle_,
    429                                  new_endpoint,
    430                                  reinterpret_cast<uint8*>(buffer->data()),
    431                                  static_cast<int>(length),
    432                                  &UsbDeviceHandleImpl::PlatformTransferCallback,
    433                                  this,
    434                                  timeout);
    435 
    436   PostOrSubmitTransfer(
    437       transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback);
    438 }
    439 
    440 void UsbDeviceHandleImpl::IsochronousTransfer(
    441     const UsbEndpointDirection direction,
    442     const uint8 endpoint,
    443     net::IOBuffer* buffer,
    444     const size_t length,
    445     const unsigned int packets,
    446     const unsigned int packet_length,
    447     const unsigned int timeout,
    448     const UsbTransferCallback& callback) {
    449   if (!device_) {
    450     callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0);
    451     return;
    452   }
    453 
    454   const uint64 total_length = packets * packet_length;
    455   CHECK(packets <= length && total_length <= length)
    456       << "transfer length is too small";
    457 
    458   PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets);
    459   const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint;
    460   libusb_fill_iso_transfer(transfer,
    461                            handle_,
    462                            new_endpoint,
    463                            reinterpret_cast<uint8*>(buffer->data()),
    464                            static_cast<int>(length),
    465                            packets,
    466                            &UsbDeviceHandleImpl::PlatformTransferCallback,
    467                            this,
    468                            timeout);
    469   libusb_set_iso_packet_lengths(transfer, packet_length);
    470 
    471   PostOrSubmitTransfer(
    472       transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback);
    473 }
    474 
    475 void UsbDeviceHandleImpl::RefreshEndpointMap() {
    476   DCHECK(thread_checker_.CalledOnValidThread());
    477   endpoint_map_.clear();
    478   for (ClaimedInterfaceMap::iterator claimedIt = claimed_interfaces_.begin();
    479        claimedIt != claimed_interfaces_.end();
    480        ++claimedIt) {
    481     for (UsbInterfaceDescriptor::Iterator ifaceIt = config_.interfaces.begin();
    482          ifaceIt != config_.interfaces.end();
    483          ++ifaceIt) {
    484       if (ifaceIt->interface_number == claimedIt->first &&
    485           ifaceIt->alternate_setting ==
    486               claimedIt->second->alternate_setting()) {
    487         for (UsbEndpointDescriptor::Iterator endpointIt =
    488                  ifaceIt->endpoints.begin();
    489              endpointIt != ifaceIt->endpoints.end();
    490              ++endpointIt) {
    491           endpoint_map_[endpointIt->address] = claimedIt->first;
    492         }
    493         break;
    494       }
    495     }
    496   }
    497 }
    498 
    499 scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
    500 UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) {
    501   if (ContainsKey(endpoint_map_, endpoint))
    502     return claimed_interfaces_[endpoint_map_[endpoint]];
    503   return NULL;
    504 }
    505 
    506 void UsbDeviceHandleImpl::PostOrSubmitTransfer(
    507     PlatformUsbTransferHandle transfer,
    508     UsbTransferType transfer_type,
    509     net::IOBuffer* buffer,
    510     size_t length,
    511     const UsbTransferCallback& callback) {
    512   if (task_runner_->RunsTasksOnCurrentThread()) {
    513     SubmitTransfer(transfer,
    514                    transfer_type,
    515                    buffer,
    516                    length,
    517                    base::ThreadTaskRunnerHandle::Get(),
    518                    callback);
    519   } else {
    520     task_runner_->PostTask(FROM_HERE,
    521                            base::Bind(&UsbDeviceHandleImpl::SubmitTransfer,
    522                                       this,
    523                                       transfer,
    524                                       transfer_type,
    525                                       make_scoped_refptr(buffer),
    526                                       length,
    527                                       base::ThreadTaskRunnerHandle::Get(),
    528                                       callback));
    529   }
    530 }
    531 
    532 void UsbDeviceHandleImpl::SubmitTransfer(
    533     PlatformUsbTransferHandle handle,
    534     UsbTransferType transfer_type,
    535     net::IOBuffer* buffer,
    536     const size_t length,
    537     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
    538     const UsbTransferCallback& callback) {
    539   DCHECK(thread_checker_.CalledOnValidThread());
    540 
    541   Transfer transfer;
    542   transfer.transfer_type = transfer_type;
    543   transfer.buffer = buffer;
    544   transfer.length = length;
    545   transfer.callback = callback;
    546   transfer.task_runner = task_runner;
    547 
    548   if (!device_) {
    549     transfer.Complete(USB_TRANSFER_DISCONNECT, 0);
    550     return;
    551   }
    552 
    553   // It's OK for this method to return NULL. libusb_submit_transfer will fail if
    554   // it requires an interface we didn't claim.
    555   transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint);
    556 
    557   const int rv = libusb_submit_transfer(handle);
    558   if (rv == LIBUSB_SUCCESS) {
    559     transfers_[handle] = transfer;
    560   } else {
    561     VLOG(1) << "Failed to submit transfer: "
    562             << ConvertPlatformUsbErrorToString(rv);
    563     transfer.Complete(USB_TRANSFER_ERROR, 0);
    564   }
    565 }
    566 
    567 /* static */
    568 void LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback(
    569     PlatformUsbTransferHandle transfer) {
    570   UsbDeviceHandleImpl* device_handle =
    571       reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data);
    572   device_handle->task_runner_->PostTask(
    573       FROM_HERE,
    574       base::Bind(
    575           &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer));
    576 }
    577 
    578 void UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) {
    579   DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed";
    580 
    581   Transfer transfer = transfers_[handle];
    582   transfers_.erase(handle);
    583 
    584   DCHECK_GE(handle->actual_length, 0) << "Negative actual length received";
    585   size_t actual_length =
    586       static_cast<size_t>(std::max(handle->actual_length, 0));
    587 
    588   DCHECK(transfer.length >= actual_length)
    589       << "data too big for our buffer (libusb failure?)";
    590 
    591   switch (transfer.transfer_type) {
    592     case USB_TRANSFER_CONTROL:
    593       // If the transfer is a control transfer we do not expose the control
    594       // setup header to the caller. This logic strips off the header if
    595       // present before invoking the callback provided with the transfer.
    596       if (actual_length > 0) {
    597         CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE)
    598             << "buffer was not correctly set: too small for the control header";
    599 
    600         if (transfer.length >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) {
    601           // If the payload is zero bytes long, pad out the allocated buffer
    602           // size to one byte so that an IOBuffer of that size can be allocated.
    603           scoped_refptr<net::IOBuffer> resized_buffer =
    604               new net::IOBuffer(static_cast<int>(
    605                   std::max(actual_length, static_cast<size_t>(1))));
    606           memcpy(resized_buffer->data(),
    607                  transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE,
    608                  actual_length);
    609           transfer.buffer = resized_buffer;
    610         }
    611       }
    612       break;
    613 
    614     case USB_TRANSFER_ISOCHRONOUS:
    615       // Isochronous replies might carry data in the different isoc packets even
    616       // if the transfer actual_data value is zero. Furthermore, not all of the
    617       // received packets might contain data, so we need to calculate how many
    618       // data bytes we are effectively providing and pack the results.
    619       if (actual_length == 0) {
    620         size_t packet_buffer_start = 0;
    621         for (int i = 0; i < handle->num_iso_packets; ++i) {
    622           PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i];
    623           if (packet->actual_length > 0) {
    624             // We don't need to copy as long as all packets until now provide
    625             // all the data the packet can hold.
    626             if (actual_length < packet_buffer_start) {
    627               CHECK(packet_buffer_start + packet->actual_length <=
    628                     transfer.length);
    629               memmove(transfer.buffer->data() + actual_length,
    630                       transfer.buffer->data() + packet_buffer_start,
    631                       packet->actual_length);
    632             }
    633             actual_length += packet->actual_length;
    634           }
    635 
    636           packet_buffer_start += packet->length;
    637         }
    638       }
    639       break;
    640 
    641     case USB_TRANSFER_BULK:
    642     case USB_TRANSFER_INTERRUPT:
    643       break;
    644 
    645     default:
    646       NOTREACHED() << "Invalid usb transfer type";
    647       break;
    648   }
    649 
    650   transfer.Complete(ConvertTransferStatus(handle->status), actual_length);
    651   libusb_free_transfer(handle);
    652 
    653   // Must release interface first before actually delete this.
    654   transfer.claimed_interface = NULL;
    655 }
    656 
    657 bool UsbDeviceHandleImpl::GetSupportedLanguages() {
    658   if (!languages_.empty()) {
    659     return true;
    660   }
    661 
    662   // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s).
    663   uint16 languages[128];
    664   int size = libusb_get_string_descriptor(
    665       handle_,
    666       0,
    667       0,
    668       reinterpret_cast<unsigned char*>(&languages[0]),
    669       sizeof(languages));
    670   if (size < 0) {
    671     VLOG(1) << "Failed to get list of supported languages: "
    672             << ConvertPlatformUsbErrorToString(size);
    673     return false;
    674   } else if (size < 2) {
    675     VLOG(1) << "String descriptor zero has no header.";
    676     return false;
    677     // The first 2 bytes of the descriptor are the total length and type tag.
    678   } else if ((languages[0] & 0xff) != size) {
    679     VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff)
    680             << " != " << size;
    681     return false;
    682   } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) {
    683     VLOG(1) << "String descriptor zero is not a string descriptor.";
    684     return false;
    685   }
    686 
    687   languages_.assign(languages[1], languages[(size - 2) / 2]);
    688   return true;
    689 }
    690 
    691 void UsbDeviceHandleImpl::InternalClose() {
    692   DCHECK(thread_checker_.CalledOnValidThread());
    693   if (!device_)
    694     return;
    695 
    696   // Cancel all the transfers.
    697   for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end();
    698        ++it) {
    699     // The callback will be called some time later.
    700     libusb_cancel_transfer(it->first);
    701   }
    702 
    703   // Attempt-release all the interfaces.
    704   // It will be retained until the transfer cancellation is finished.
    705   claimed_interfaces_.clear();
    706 
    707   // Cannot close device handle here. Need to wait for libusb_cancel_transfer to
    708   // finish.
    709   device_ = NULL;
    710 }
    711 
    712 }  // namespace device
    713