usb_linux.cpp revision 0b156638307db890e5539b52521fd24beb3440cb
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * All rights reserved. 4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without 6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met: 8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * * Redistributions of source code must retain the above copyright 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * notice, this list of conditions and the following disclaimer. 10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * notice, this list of conditions and the following disclaimer in 125ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau * the documentation and/or other materials provided with the 13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distribution. 14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE. 27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 2993f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <ctype.h> 3093f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <dirent.h> 3193f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <errno.h> 3293f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <fcntl.h> 3393f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <pthread.h> 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h> 3813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson#include <sys/stat.h> 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 4093f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes#include <unistd.h> 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usbdevice_fs.h> 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/version.h> 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usb/ch9.h> 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 460b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include <memory> 470b156638307db890e5539b52521fd24beb3440cbDavid Pursell 48157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler#include "fastboot.h" 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "usb.h" 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 51b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#define MAX_RETRIES 5 52b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 53157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler/* Timeout in seconds for usb_wait_for_disconnect. 54157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * It doesn't usually take long for a device to disconnect (almost always 55157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * under 2 seconds) but we'll time out after 3 seconds just in case. 56157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler */ 57157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler#define WAIT_FOR_DISCONNECT_TIMEOUT 3 58157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler 59b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#ifdef TRACE_USB 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) fprintf(stderr, x) 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) fprintf(stderr, x) 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 6793f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// Kernels before 3.3 have a 16KiB transfer limit. That limit was replaced 6893f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// with a 16MiB global limit in 3.3, but each URB submitted required a 6993f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// contiguous kernel allocation, so you would get ENOMEM if you tried to 7093f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// send something larger than the biggest available contiguous kernel 7193f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// memory region. 256KiB contiguous allocations are generally not reliable 7293f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// on a device kernel that has been running for a while fragmenting its 7393f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// memory, but that shouldn't be a problem for fastboot on the host. 7493f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// In 3.6, the contiguous buffer limit was removed by allocating multiple 7593f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// 16KiB chunks and having the USB driver stitch them back together while 7693f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// transmitting using a scatter-gather list, so 256KiB bulk transfers should 7793f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// be reliable. 7893f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// 256KiB seems to work, but 1MiB bulk transfers lock up my z620 with a 3.13 7993f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// kernel. 80913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause#define MAX_USBFS_BULK_SIZE (16 * 1024) 81913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause 825ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazaustruct usb_handle 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char fname[64]; 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int desc; 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_in; 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_out; 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 900b156638307db890e5539b52521fd24beb3440cbDavid Pursellclass LinuxUsbTransport : public Transport { 910b156638307db890e5539b52521fd24beb3440cbDavid Pursell public: 920b156638307db890e5539b52521fd24beb3440cbDavid Pursell LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {} 930b156638307db890e5539b52521fd24beb3440cbDavid Pursell ~LinuxUsbTransport() override = default; 940b156638307db890e5539b52521fd24beb3440cbDavid Pursell 950b156638307db890e5539b52521fd24beb3440cbDavid Pursell ssize_t Read(void* data, size_t len) override; 960b156638307db890e5539b52521fd24beb3440cbDavid Pursell ssize_t Write(const void* data, size_t len) override; 970b156638307db890e5539b52521fd24beb3440cbDavid Pursell int Close() override; 980b156638307db890e5539b52521fd24beb3440cbDavid Pursell int WaitForDisconnect() override; 990b156638307db890e5539b52521fd24beb3440cbDavid Pursell 1000b156638307db890e5539b52521fd24beb3440cbDavid Pursell private: 1010b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> handle_; 1020b156638307db890e5539b52521fd24beb3440cbDavid Pursell 1030b156638307db890e5539b52521fd24beb3440cbDavid Pursell DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport); 1040b156638307db890e5539b52521fd24beb3440cbDavid Pursell}; 1050b156638307db890e5539b52521fd24beb3440cbDavid Pursell 106bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler/* True if name isn't a valid name for a USB device in /sys/bus/usb/devices. 107bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * Device names are made up of numbers, dots, and dashes, e.g., '7-1.5'. 108bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * We reject interfaces (e.g., '7-1.5:1.0') and host controllers (e.g. 'usb1'). 109bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * The name must also start with a digit, to disallow '.' and '..' 110bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler */ 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int badname(const char *name) 112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 113bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (!isdigit(*name)) 114bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 1; 115bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler while(*++name) { 116bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if(!isdigit(*name) && *name != '.' && *name != '-') 117bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 1; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int check(void *_desc, int len, unsigned type, int size) 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 124aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)_desc; 1255ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len < size) return -1; 127aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bLength < size) return -1; 128aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bLength > len) return -1; 129aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bDescriptorType != type) return -1; 1305ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 134157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachslerstatic int filter_usb_device(char* sysfs_name, 135bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char *ptr, int len, int writable, 136b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes ifc_match_func callback, 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int *ept_in_id, int *ept_out_id, int *ifc_id) 138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_device_descriptor *dev; 140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_config_descriptor *cfg; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_interface_descriptor *ifc; 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_endpoint_descriptor *ept; 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_ifc_info info; 1445ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int in, out; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned i; 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned e; 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 149aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE)) 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 151aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin dev = (struct usb_device_descriptor *)ptr; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= dev->bLength; 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += dev->bLength; 1545ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 155aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE)) 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 157aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin cfg = (struct usb_config_descriptor *)ptr; 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= cfg->bLength; 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += cfg->bLength; 1605ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_vendor = dev->idVendor; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_product = dev->idProduct; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_class = dev->bDeviceClass; 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_subclass = dev->bDeviceSubClass; 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_protocol = dev->bDeviceProtocol; 166b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes info.writable = writable; 1675ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 168bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(info.device_path, sizeof(info.device_path), "usb:%s", sysfs_name); 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 170bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler /* Read device serial number (if there is one). 171bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * We read the serial number from sysfs, since it's faster and more 172bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * reliable than issuing a control pipe read, and also won't 173bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * cause problems for devices which don't like getting descriptor 174bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * requests while they're in the middle of flashing. 17513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson */ 176bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[0] = '\0'; 177bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (dev->iSerialNumber) { 178bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char path[80]; 179bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int fd; 180bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 181bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(path, sizeof(path), 182bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler "/sys/bus/usb/devices/%s/serial", sysfs_name); 183bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler path[sizeof(path) - 1] = '\0'; 184bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 185bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler fd = open(path, O_RDONLY); 186bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (fd >= 0) { 187bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int chars_read = read(fd, info.serial_number, 188bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler sizeof(info.serial_number) - 1); 189bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler close(fd); 190bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 191bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (chars_read <= 0) 192bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[0] = '\0'; 193bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler else if (info.serial_number[chars_read - 1] == '\n') { 194bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler // strip trailing newline 195bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[chars_read - 1] = '\0'; 196bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler } 19713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 19813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 19913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(i = 0; i < cfg->bNumInterfaces; i++) { 201aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 202aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin while (len > 0) { 203aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr; 204aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(hdr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE) == 0) 205aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 206aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin len -= hdr->bLength; 207aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ptr += hdr->bLength; 208aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 209aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 210aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (len <= 0) 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 212aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 213aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ifc = (struct usb_interface_descriptor *)ptr; 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ifc->bLength; 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ifc->bLength; 2165ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = -1; 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = -1; 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_class = ifc->bInterfaceClass; 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_subclass = ifc->bInterfaceSubClass; 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_protocol = ifc->bInterfaceProtocol; 2225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(e = 0; e < ifc->bNumEndpoints; e++) { 224aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin while (len > 0) { 225aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr; 226aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(hdr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE) == 0) 227aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 228aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin len -= hdr->bLength; 229aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ptr += hdr->bLength; 230aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 231aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (len < 0) { 232aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 233aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 234aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 235aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ept = (struct usb_endpoint_descriptor *)ptr; 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ept->bLength; 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ept->bLength; 2385ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 239aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if((ept->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 2415ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 242aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(ept->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = ept->bEndpointAddress; 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = ept->bEndpointAddress; 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 2471c02213e89f99c6f532b27048feb8f3170cac296Jack Pham 2481c02213e89f99c6f532b27048feb8f3170cac296Jack Pham // For USB 3.0 devices skip the SS Endpoint Companion descriptor 2491c02213e89f99c6f532b27048feb8f3170cac296Jack Pham if (check((struct usb_descriptor_hdr *)ptr, len, 2501c02213e89f99c6f532b27048feb8f3170cac296Jack Pham USB_DT_SS_ENDPOINT_COMP, USB_DT_SS_EP_COMP_SIZE) == 0) { 2511c02213e89f99c6f532b27048feb8f3170cac296Jack Pham len -= USB_DT_SS_EP_COMP_SIZE; 2521c02213e89f99c6f532b27048feb8f3170cac296Jack Pham ptr += USB_DT_SS_EP_COMP_SIZE; 2531c02213e89f99c6f532b27048feb8f3170cac296Jack Pham } 254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_in = (in != -1); 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_out = (out != -1); 2585ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(callback(&info) == 0) { 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_in_id = in; 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_out_id = out; 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ifc_id = ifc->bInterfaceNumber; 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 270bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int read_sysfs_string(const char *sysfs_name, const char *sysfs_node, 271bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char* buf, int bufsize) 272bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 273bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char path[80]; 274bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int fd, n; 275bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 276bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(path, sizeof(path), 277bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler "/sys/bus/usb/devices/%s/%s", sysfs_name, sysfs_node); 278bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler path[sizeof(path) - 1] = '\0'; 279bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 280bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler fd = open(path, O_RDONLY); 281bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (fd < 0) 282bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 283bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 284bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler n = read(fd, buf, bufsize - 1); 285bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler close(fd); 286bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 287bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (n < 0) 288bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 289bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 290bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler buf[n] = '\0'; 291bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 292bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return n; 293bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 294bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 295bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int read_sysfs_number(const char *sysfs_name, const char *sysfs_node) 296bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 297bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char buf[16]; 298bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int value; 299bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 300bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (read_sysfs_string(sysfs_name, sysfs_node, buf, sizeof(buf)) < 0) 301bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 302bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 303bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (sscanf(buf, "%d", &value) != 1) 304bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 305bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 306bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return value; 307bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 308bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 309bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler/* Given the name of a USB device in sysfs, get the name for the same 310bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * device in devfs. Returns 0 for success, -1 for failure. 311bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler */ 312bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int convert_to_devfs_name(const char* sysfs_name, 313bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char* devname, int devname_size) 314bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 315bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int busnum, devnum; 316bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 317bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler busnum = read_sysfs_number(sysfs_name, "busnum"); 318bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (busnum < 0) 319bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 320bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 321bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler devnum = read_sysfs_number(sysfs_name, "devnum"); 322bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (devnum < 0) 323bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 324bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 325bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(devname, devname_size, "/dev/bus/usb/%03d/%03d", busnum, devnum); 326bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 0; 327bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 328bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 3290b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic std::unique_ptr<usb_handle> find_usb_device(const char* base, ifc_match_func callback) 330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 3310b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> usb; 332bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char devname[64]; 333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char desc[1024]; 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n, in, out, ifc; 3355ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 336bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler DIR *busdir; 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 339c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes int writable; 3405ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project busdir = opendir(base); 3420b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (busdir == 0) return 0; 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3440b156638307db890e5539b52521fd24beb3440cbDavid Pursell while ((de = readdir(busdir)) && (usb == nullptr)) { 3450b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (badname(de->d_name)) continue; 3465ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 3470b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// DBG("[ scanning %s ]\n", devname); 350c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes writable = 1; 3510b156638307db890e5539b52521fd24beb3440cbDavid Pursell if ((fd = open(devname, O_RDWR)) < 0) { 352b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // Check if we have read-only access, so we can give a helpful 353b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // diagnostic like "adb devices" does. 354b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes writable = 0; 3550b156638307db890e5539b52521fd24beb3440cbDavid Pursell if ((fd = open(devname, O_RDONLY)) < 0) { 356b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes continue; 357b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes } 358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = read(fd, desc, sizeof(desc)); 3615ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 3620b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (filter_usb_device(de->d_name, desc, n, writable, callback, &in, &out, &ifc) == 0) { 3630b156638307db890e5539b52521fd24beb3440cbDavid Pursell usb.reset(new usb_handle()); 364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(usb->fname, devname); 365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_in = in; 366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_out = out; 367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->desc = fd; 368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); 3700b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (n != 0) { 371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 3720b156638307db890e5539b52521fd24beb3440cbDavid Pursell usb.reset(); 373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(busdir); 381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return usb; 383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3850b156638307db890e5539b52521fd24beb3440cbDavid Pursellssize_t LinuxUsbTransport::Write(const void* _data, size_t len) 386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3920b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (handle_->ep_out == 0 || handle_->desc == -1) { 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3955ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 396157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler do { 397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int xfer; 398913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 3995ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4000b156638307db890e5539b52521fd24beb3440cbDavid Pursell bulk.ep = handle_->ep_out; 401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 4045ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4050b156638307db890e5539b52521fd24beb3440cbDavid Pursell n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); 406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != xfer) { 407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("ERROR: n = %d, errno = %d (%s)\n", 408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n, errno, strerror(errno)); 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += xfer; 413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= xfer; 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += xfer; 415157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler } while(len > 0); 416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4200b156638307db890e5539b52521fd24beb3440cbDavid Pursellssize_t LinuxUsbTransport::Read(void* _data, size_t len) 421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 425b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy int n, retry; 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4270b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (handle_->ep_in == 0 || handle_->desc == -1) { 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4305ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(len > 0) { 432913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 4335ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4340b156638307db890e5539b52521fd24beb3440cbDavid Pursell bulk.ep = handle_->ep_in; 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 438b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy retry = 0; 439b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 440b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy do{ 4410b156638307db890e5539b52521fd24beb3440cbDavid Pursell DBG("[ usb read %d fd = %d], fname=%s\n", xfer, handle_->desc, handle_->fname); 4420b156638307db890e5539b52521fd24beb3440cbDavid Pursell n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); 4430b156638307db890e5539b52521fd24beb3440cbDavid Pursell DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, handle_->fname, retry); 444b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 445b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy if( n < 0 ) { 446b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno)); 447b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy if ( ++retry > MAX_RETRIES ) return -1; 448b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy sleep( 1 ); 449b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy } 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 451b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy while( n < 0 ); 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += n; 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= n; 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += n; 4565ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < xfer) { 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4615ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4650b156638307db890e5539b52521fd24beb3440cbDavid Pursellint LinuxUsbTransport::Close() 466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 4685ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4690b156638307db890e5539b52521fd24beb3440cbDavid Pursell fd = handle_->desc; 4700b156638307db890e5539b52521fd24beb3440cbDavid Pursell handle_->desc = -1; 471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd >= 0) { 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("[ usb closed %d ]\n", fd); 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4790b156638307db890e5539b52521fd24beb3440cbDavid PursellTransport* usb_open(ifc_match_func callback) 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 4810b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback); 4820b156638307db890e5539b52521fd24beb3440cbDavid Pursell return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr; 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 484157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler 485157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler/* Wait for the system to notice the device is gone, so that a subsequent 486157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * fastboot command won't try to access the device before it's rebooted. 487157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * Returns 0 for success, -1 for timeout. 488157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler */ 4890b156638307db890e5539b52521fd24beb3440cbDavid Pursellint LinuxUsbTransport::WaitForDisconnect() 490157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler{ 491157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler double deadline = now() + WAIT_FOR_DISCONNECT_TIMEOUT; 492157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler while (now() < deadline) { 4930b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (access(handle_->fname, F_OK)) 494157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler return 0; 495157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler usleep(50000); 496157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler } 497157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler return -1; 498157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler} 499