10529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_device_handle_impl.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include <algorithm> 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector> 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/bind.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/location.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/single_thread_task_runner.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/strings/string16.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/thread_task_runner_handle.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_context.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_descriptors.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_device_impl.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_error.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "device/usb/usb_service.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/libusb/src/libusb/libusb.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace device { 250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)typedef libusb_device* PlatformUsbDevice; 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid HandleTransferCompletion(PlatformUsbTransferHandle transfer); 29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstatic uint8 ConvertTransferDirection(const UsbEndpointDirection direction) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (direction) { 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case USB_DIRECTION_INBOUND: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ENDPOINT_IN; 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case USB_DIRECTION_OUTBOUND: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return LIBUSB_ENDPOINT_OUT; 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return LIBUSB_ENDPOINT_IN; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochstatic uint8 CreateRequestType( 450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const UsbEndpointDirection direction, 46a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch const UsbDeviceHandle::TransferRequestType request_type, 47a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch const UsbDeviceHandle::TransferRecipient recipient) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 result = ConvertTransferDirection(direction); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (request_type) { 51a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::STANDARD: 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_REQUEST_TYPE_STANDARD; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 54a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::CLASS: 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_REQUEST_TYPE_CLASS; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 57a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::VENDOR: 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_REQUEST_TYPE_VENDOR; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 60a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::RESERVED: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_REQUEST_TYPE_RESERVED; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (recipient) { 66a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::DEVICE: 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_RECIPIENT_DEVICE; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 69a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::INTERFACE: 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_RECIPIENT_INTERFACE; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 72a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::ENDPOINT: 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_RECIPIENT_ENDPOINT; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 75a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch case UsbDeviceHandle::OTHER: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result |= LIBUSB_RECIPIENT_OTHER; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static UsbTransferStatus ConvertTransferStatus( 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const libusb_transfer_status status) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_COMPLETED: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_COMPLETED; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_ERROR: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_ERROR; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_TIMED_OUT: 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_TIMEOUT; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_STALL: 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_STALLED; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_NO_DEVICE: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_DISCONNECT; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_OVERFLOW: 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_OVERFLOW; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case LIBUSB_TRANSFER_CANCELLED: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return USB_TRANSFER_CANCELLED; 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) default: 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) NOTREACHED(); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return USB_TRANSFER_ERROR; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class UsbDeviceHandleImpl::InterfaceClaimer 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> { 110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public: 111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InterfaceClaimer(const scoped_refptr<UsbDeviceHandleImpl> handle, 112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const int interface_number); 113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool Claim() const; 115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int alternate_setting() const { return alternate_setting_; } 117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch void set_alternate_setting(const int alternate_setting) { 118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alternate_setting_ = alternate_setting; 119ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private: 122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch friend class UsbDevice; 123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch friend class base::RefCountedThreadSafe<InterfaceClaimer>; 124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ~InterfaceClaimer(); 125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const scoped_refptr<UsbDeviceHandleImpl> handle_; 127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const int interface_number_; 128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int alternate_setting_; 129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DISALLOW_COPY_AND_ASSIGN(InterfaceClaimer); 131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}; 132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer( 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const scoped_refptr<UsbDeviceHandleImpl> handle, 1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int interface_number) 136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch : handle_(handle), 137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch interface_number_(interface_number), 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch alternate_setting_(0) { 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() { 142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch libusb_release_interface(handle_->handle(), interface_number_); 143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool UsbDeviceHandleImpl::InterfaceClaimer::Claim() const { 1466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int rv = libusb_claim_interface(handle_->handle(), interface_number_); 1476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (rv != LIBUSB_SUCCESS) { 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Failed to claim interface: " 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ConvertPlatformUsbErrorToString(rv); 1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return rv == LIBUSB_SUCCESS; 152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct UsbDeviceHandleImpl::Transfer { 155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Transfer(); 156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ~Transfer(); 157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void Complete(UsbTransferStatus status, size_t bytes_transferred); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UsbTransferType transfer_type; 161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<net::IOBuffer> buffer; 162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface; 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<base::SingleThreadTaskRunner> task_runner; 164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch size_t length; 165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UsbTransferCallback callback; 166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}; 167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::Transfer::Transfer() 1690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : transfer_type(USB_TRANSFER_CONTROL), length(0) { 170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::Transfer::~Transfer() { 1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid UsbDeviceHandleImpl::Transfer::Complete(UsbTransferStatus status, 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t bytes_transferred) { 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (task_runner->RunsTasksOnCurrentThread()) { 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback.Run(status, buffer, bytes_transferred); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner->PostTask( 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, base::Bind(callback, status, buffer, bytes_transferred)); 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciUsbDeviceHandleImpl::UsbDeviceHandleImpl(scoped_refptr<UsbContext> context, 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UsbDeviceImpl* device, 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformUsbDeviceHandle handle, 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const UsbConfigDescriptor& config) 189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) : device_(device), 190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) handle_(handle), 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci config_(config), 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context_(context), 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_(base::ThreadTaskRunnerHandle::Get()) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(handle) << "Cannot create device with NULL handle."; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::~UsbDeviceHandleImpl() { 198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch libusb_close(handle_); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handle_ = NULL; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const { 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<UsbDevice*>(device_); 206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::Close() { 209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 210ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (device_) 211ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch device_->Close(this); 212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool UsbDeviceHandleImpl::ClaimInterface(const int interface_number) { 215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 2160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!device_) 2170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (ContainsKey(claimed_interfaces_, interface_number)) 2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return true; 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 221ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<InterfaceClaimer> claimer = 222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch new InterfaceClaimer(this, interface_number); 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (claimer->Claim()) { 2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch claimed_interfaces_[interface_number] = claimer; 226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RefreshEndpointMap(); 227ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return true; 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return false; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool UsbDeviceHandleImpl::ReleaseInterface(const int interface_number) { 233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 2340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!device_) 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!ContainsKey(claimed_interfaces_, interface_number)) 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Cancel all the transfers on that interface. 240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch InterfaceClaimer* interface_claimer = 241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch claimed_interfaces_[interface_number].get(); 2420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (it->second.claimed_interface.get() == interface_claimer) 245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch libusb_cancel_transfer(it->first); 246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch claimed_interfaces_.erase(interface_number); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RefreshEndpointMap(); 250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return true; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool UsbDeviceHandleImpl::SetInterfaceAlternateSetting( 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int interface_number, 255a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch const int alternate_setting) { 256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 2570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!device_) 2580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!ContainsKey(claimed_interfaces_, interface_number)) 2600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 2610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const int rv = libusb_set_interface_alt_setting( 2620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle_, interface_number, alternate_setting); 2636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (rv == LIBUSB_SUCCESS) { 2640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch claimed_interfaces_[interface_number]->set_alternate_setting( 2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch alternate_setting); 266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RefreshEndpointMap(); 2676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } else { 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VLOG(1) << "Failed to set interface (" << interface_number << ", " 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << alternate_setting 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "): " << ConvertPlatformUsbErrorToString(rv); 271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 2726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return rv == LIBUSB_SUCCESS; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool UsbDeviceHandleImpl::ResetDevice() { 276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!device_) 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return false; 279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 2806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int rv = libusb_reset_device(handle_); 2816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (rv != LIBUSB_SUCCESS) { 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Failed to reset device: " 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ConvertPlatformUsbErrorToString(rv); 2846d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 2856d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return rv == LIBUSB_SUCCESS; 286a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch} 287a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch 2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool UsbDeviceHandleImpl::GetStringDescriptor(uint8 string_id, 2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::string16* string) { 2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (!GetSupportedLanguages()) { 291bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return false; 2926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) } 293bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) std::map<uint8, base::string16>::const_iterator it = strings_.find(string_id); 2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (it != strings_.end()) { 2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *string = it->second; 2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return true; 2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 299bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (size_t i = 0; i < languages_.size(); ++i) { 301bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Get the string using language ID. 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) uint16 language_id = languages_[i]; 3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // The 1-byte length field limits the descriptor to 256-bytes (128 char16s). 3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) base::char16 text[128]; 3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int size = 3060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch libusb_get_string_descriptor(handle_, 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) string_id, 3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) language_id, 3090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<unsigned char*>(&text[0]), 3100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch sizeof(text)); 3116d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (size < 0) { 3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(1) << "Failed to get string descriptor " << string_id << " (langid " 3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << language_id << "): " << ConvertPlatformUsbErrorToString(size); 3146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) continue; 3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if (size < 2) { 3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ") has no header."; 318bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch continue; 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The first 2 bytes of the descriptor are the total length and type tag. 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if ((text[0] & 0xff) != size) { 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ") size mismatch: " << (text[0] & 0xff) << " != " << size; 323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } else if ((text[0] >> 8) != LIBUSB_DT_STRING) { 3256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) VLOG(1) << "String descriptor " << string_id << " (langid " << language_id 3266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) << ") is not a string descriptor."; 327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 3306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *string = base::string16(text + 1, (size - 2) / 2); 3316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) strings_[string_id] = *string; 332bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return true; 333bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 3346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return false; 336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch} 337bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::ControlTransfer( 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbEndpointDirection direction, 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const TransferRequestType request_type, 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const TransferRecipient recipient, 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint8 request, 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint16 value, 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint16 index, 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::IOBuffer* buffer, 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t length, 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int timeout, 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbTransferCallback& callback) { 349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!device_) { 350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 351ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + length; 3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch scoped_refptr<net::IOBuffer> resized_buffer( 3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new net::IOBufferWithSize(static_cast<int>(resized_length))); 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!resized_buffer.get()) { 3580529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch callback.Run(USB_TRANSFER_ERROR, buffer, 0); 3590529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 3600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 3610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch memcpy(resized_buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 3620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch buffer->data(), 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(length)); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const uint8 converted_type = 3670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CreateRequestType(direction, request_type, recipient); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_fill_control_setup(reinterpret_cast<uint8*>(resized_buffer->data()), 3690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch converted_type, 3700529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch request, 3710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch value, 3720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch index, 3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int16>(length)); 3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch libusb_fill_control_transfer(transfer, 3750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle_, 3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<uint8*>(resized_buffer->data()), 3771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &UsbDeviceHandleImpl::PlatformTransferCallback, 3780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this, 3790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch timeout); 3800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostOrSubmitTransfer(transfer, 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci USB_TRANSFER_CONTROL, 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci resized_buffer.get(), 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci resized_length, 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::BulkTransfer(const UsbEndpointDirection direction, 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint8 endpoint, 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::IOBuffer* buffer, 391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t length, 392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int timeout, 393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbTransferCallback& callback) { 394ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!device_) { 395ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 396ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 4010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch libusb_fill_bulk_transfer(transfer, 4020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle_, 4030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_endpoint, 4040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<uint8*>(buffer->data()), 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(length), 4061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &UsbDeviceHandleImpl::PlatformTransferCallback, 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this, 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch timeout); 409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 4101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostOrSubmitTransfer(transfer, USB_TRANSFER_BULK, buffer, length, callback); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::InterruptTransfer( 414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbEndpointDirection direction, 415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint8 endpoint, 416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::IOBuffer* buffer, 417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t length, 418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int timeout, 419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbTransferCallback& callback) { 420ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!device_) { 421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 422ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(0); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 4270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch libusb_fill_interrupt_transfer(transfer, 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle_, 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_endpoint, 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<uint8*>(buffer->data()), 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(length), 4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &UsbDeviceHandleImpl::PlatformTransferCallback, 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this, 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch timeout); 4351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostOrSubmitTransfer( 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer, USB_TRANSFER_INTERRUPT, buffer, length, callback); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::IsochronousTransfer( 441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbEndpointDirection direction, 442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const uint8 endpoint, 443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) net::IOBuffer* buffer, 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const size_t length, 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int packets, 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int packet_length, 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const unsigned int timeout, 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const UsbTransferCallback& callback) { 449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!device_) { 450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback.Run(USB_TRANSFER_DISCONNECT, buffer, 0); 451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint64 total_length = packets * packet_length; 4550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CHECK(packets <= length && total_length <= length) 4560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch << "transfer length is too small"; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PlatformUsbTransferHandle const transfer = libusb_alloc_transfer(packets); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8 new_endpoint = ConvertTransferDirection(direction) | endpoint; 4600529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch libusb_fill_iso_transfer(transfer, 4610529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch handle_, 4620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch new_endpoint, 4630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch reinterpret_cast<uint8*>(buffer->data()), 4640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch static_cast<int>(length), 4650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch packets, 4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &UsbDeviceHandleImpl::PlatformTransferCallback, 4670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch this, 4680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch timeout); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) libusb_set_iso_packet_lengths(transfer, packet_length); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PostOrSubmitTransfer( 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer, USB_TRANSFER_ISOCHRONOUS, buffer, length, callback); 473ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 474ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::RefreshEndpointMap() { 476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch endpoint_map_.clear(); 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (ClaimedInterfaceMap::iterator claimedIt = claimed_interfaces_.begin(); 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci claimedIt != claimed_interfaces_.end(); 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++claimedIt) { 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (UsbInterfaceDescriptor::Iterator ifaceIt = config_.interfaces.begin(); 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ifaceIt != config_.interfaces.end(); 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++ifaceIt) { 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ifaceIt->interface_number == claimedIt->first && 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ifaceIt->alternate_setting == 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci claimedIt->second->alternate_setting()) { 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (UsbEndpointDescriptor::Iterator endpointIt = 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ifaceIt->endpoints.begin(); 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci endpointIt != ifaceIt->endpoints.end(); 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++endpointIt) { 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci endpoint_map_[endpointIt->address] = claimedIt->first; 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> 500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(unsigned char endpoint) { 501f453b36b86edd15382a7e4da454f6bb02a848b5cBen Murdoch if (ContainsKey(endpoint_map_, endpoint)) 502f453b36b86edd15382a7e4da454f6bb02a848b5cBen Murdoch return claimed_interfaces_[endpoint_map_[endpoint]]; 503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return NULL; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid UsbDeviceHandleImpl::PostOrSubmitTransfer( 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformUsbTransferHandle transfer, 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UsbTransferType transfer_type, 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci net::IOBuffer* buffer, 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t length, 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const UsbTransferCallback& callback) { 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (task_runner_->RunsTasksOnCurrentThread()) { 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SubmitTransfer(transfer, 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer_type, 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer, 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci length, 5171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadTaskRunnerHandle::Get(), 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback); 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_runner_->PostTask(FROM_HERE, 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind(&UsbDeviceHandleImpl::SubmitTransfer, 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer, 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer_type, 5251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci make_scoped_refptr(buffer), 5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci length, 5271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::ThreadTaskRunnerHandle::Get(), 5281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci callback)); 5291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::SubmitTransfer( 533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PlatformUsbTransferHandle handle, 534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch UsbTransferType transfer_type, 535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch net::IOBuffer* buffer, 536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const size_t length, 5371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<base::SingleThreadTaskRunner> task_runner, 538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const UsbTransferCallback& callback) { 539ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Transfer transfer; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfer.transfer_type = transfer_type; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfer.buffer = buffer; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfer.length = length; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfer.callback = callback; 5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.task_runner = task_runner; 5471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!device_) { 5491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.Complete(USB_TRANSFER_DISCONNECT, 0); 5501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 5511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 552ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 553ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // It's OK for this method to return NULL. libusb_submit_transfer will fail if 554ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // it requires an interface we didn't claim. 555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch transfer.claimed_interface = GetClaimedInterfaceForEndpoint(handle->endpoint); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) const int rv = libusb_submit_transfer(handle); 5586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if (rv == LIBUSB_SUCCESS) { 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transfers_[handle] = transfer; 560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 5611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Failed to submit transfer: " 5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ConvertPlatformUsbErrorToString(rv); 5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.Complete(USB_TRANSFER_ERROR, 0); 5641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/* static */ 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid LIBUSB_CALL UsbDeviceHandleImpl::PlatformTransferCallback( 5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformUsbTransferHandle transfer) { 5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UsbDeviceHandleImpl* device_handle = 5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reinterpret_cast<UsbDeviceHandleImpl*>(transfer->user_data); 5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci device_handle->task_runner_->PostTask( 5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci FROM_HERE, 5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::Bind( 5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &UsbDeviceHandleImpl::CompleteTransfer, device_handle, transfer)); 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid UsbDeviceHandleImpl::CompleteTransfer(PlatformUsbTransferHandle handle) { 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(ContainsKey(transfers_, handle)) << "Missing transfer completed"; 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Transfer transfer = transfers_[handle]; 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfers_.erase(handle); 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_GE(handle->actual_length, 0) << "Negative actual length received"; 5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t actual_length = 5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<size_t>(std::max(handle->actual_length, 0)); 5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(transfer.length >= actual_length) 5891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "data too big for our buffer (libusb failure?)"; 5901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (transfer.transfer_type) { 5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case USB_TRANSFER_CONTROL: 5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the transfer is a control transfer we do not expose the control 5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // setup header to the caller. This logic strips off the header if 5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // present before invoking the callback provided with the transfer. 5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (actual_length > 0) { 5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(transfer.length >= LIBUSB_CONTROL_SETUP_SIZE) 5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << "buffer was not correctly set: too small for the control header"; 5991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (transfer.length >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) { 6011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the payload is zero bytes long, pad out the allocated buffer 6021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // size to one byte so that an IOBuffer of that size can be allocated. 6031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_refptr<net::IOBuffer> resized_buffer = 6041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new net::IOBuffer(static_cast<int>( 6051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::max(actual_length, static_cast<size_t>(1)))); 6061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memcpy(resized_buffer->data(), 6071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.buffer->data() + LIBUSB_CONTROL_SETUP_SIZE, 6081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci actual_length); 6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.buffer = resized_buffer; 6101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 6131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case USB_TRANSFER_ISOCHRONOUS: 6151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Isochronous replies might carry data in the different isoc packets even 6161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // if the transfer actual_data value is zero. Furthermore, not all of the 6171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // received packets might contain data, so we need to calculate how many 6181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // data bytes we are effectively providing and pack the results. 6191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (actual_length == 0) { 6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t packet_buffer_start = 0; 6211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (int i = 0; i < handle->num_iso_packets; ++i) { 6221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PlatformUsbIsoPacketDescriptor packet = &handle->iso_packet_desc[i]; 6231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (packet->actual_length > 0) { 6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We don't need to copy as long as all packets until now provide 6251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // all the data the packet can hold. 6261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (actual_length < packet_buffer_start) { 6271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CHECK(packet_buffer_start + packet->actual_length <= 6281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.length); 6291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memmove(transfer.buffer->data() + actual_length, 6301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.buffer->data() + packet_buffer_start, 6311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci packet->actual_length); 6321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci actual_length += packet->actual_length; 6341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci packet_buffer_start += packet->length; 6371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 6401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case USB_TRANSFER_BULK: 6421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case USB_TRANSFER_INTERRUPT: 6431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 6441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 6461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NOTREACHED() << "Invalid usb transfer type"; 6471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci break; 648ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 6491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.Complete(ConvertTransferStatus(handle->status), actual_length); 6511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci libusb_free_transfer(handle); 6521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Must release interface first before actually delete this. 6541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci transfer.claimed_interface = NULL; 6551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 6561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool UsbDeviceHandleImpl::GetSupportedLanguages() { 6581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!languages_.empty()) { 6591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 6601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The 1-byte length field limits the descriptor to 256-bytes (128 uint16s). 6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint16 languages[128]; 6641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int size = libusb_get_string_descriptor( 6651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci handle_, 6661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 6671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 0, 6681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci reinterpret_cast<unsigned char*>(&languages[0]), 6691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci sizeof(languages)); 6701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (size < 0) { 6711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "Failed to get list of supported languages: " 6721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << ConvertPlatformUsbErrorToString(size); 6731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 6741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (size < 2) { 6751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "String descriptor zero has no header."; 6761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 6771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The first 2 bytes of the descriptor are the total length and type tag. 6781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if ((languages[0] & 0xff) != size) { 6791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "String descriptor zero size mismatch: " << (languages[0] & 0xff) 6801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci << " != " << size; 6811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 6821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if ((languages[0] >> 8) != LIBUSB_DT_STRING) { 6831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VLOG(1) << "String descriptor zero is not a string descriptor."; 6841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 6851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 6861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci languages_.assign(languages[1], languages[(size - 2) / 2]); 6881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return true; 689ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 690ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 691cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UsbDeviceHandleImpl::InternalClose() { 692ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 6930529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!device_) 6940529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 695ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 696ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Cancel all the transfers. 6970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (TransferMap::iterator it = transfers_.begin(); it != transfers_.end(); 6980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 699ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The callback will be called some time later. 700ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch libusb_cancel_transfer(it->first); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 702ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 703ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Attempt-release all the interfaces. 704ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // It will be retained until the transfer cancellation is finished. 705ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch claimed_interfaces_.clear(); 706ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 707ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Cannot close device handle here. Need to wait for libusb_cancel_transfer to 708ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // finish. 709ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch device_ = NULL; 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 7121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace device 713