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 46290a228fdca935ab2e702db77516758314900c3aElliott Hughes#include <chrono> 470b156638307db890e5539b52521fd24beb3440cbDavid Pursell#include <memory> 48290a228fdca935ab2e702db77516758314900c3aElliott Hughes#include <thread> 490b156638307db890e5539b52521fd24beb3440cbDavid Pursell 50157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler#include "fastboot.h" 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "usb.h" 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 53290a228fdca935ab2e702db77516758314900c3aElliott Hughesusing namespace std::chrono_literals; 54290a228fdca935ab2e702db77516758314900c3aElliott Hughes 55b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#define MAX_RETRIES 5 56b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 57157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler/* Timeout in seconds for usb_wait_for_disconnect. 58157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * It doesn't usually take long for a device to disconnect (almost always 59157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * under 2 seconds) but we'll time out after 3 seconds just in case. 60157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler */ 61157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler#define WAIT_FOR_DISCONNECT_TIMEOUT 3 62157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler 63b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#ifdef TRACE_USB 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) fprintf(stderr, x) 65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) fprintf(stderr, x) 66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) 68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) 69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 7193f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// Kernels before 3.3 have a 16KiB transfer limit. That limit was replaced 7293f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// with a 16MiB global limit in 3.3, but each URB submitted required a 7393f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// contiguous kernel allocation, so you would get ENOMEM if you tried to 7493f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// send something larger than the biggest available contiguous kernel 7593f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// memory region. 256KiB contiguous allocations are generally not reliable 7693f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// on a device kernel that has been running for a while fragmenting its 7793f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// memory, but that shouldn't be a problem for fastboot on the host. 7893f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// In 3.6, the contiguous buffer limit was removed by allocating multiple 7993f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// 16KiB chunks and having the USB driver stitch them back together while 8093f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// transmitting using a scatter-gather list, so 256KiB bulk transfers should 8193f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// be reliable. 8293f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// 256KiB seems to work, but 1MiB bulk transfers lock up my z620 with a 3.13 8393f65faee85facd14fa58993bbcb98c357217fcbElliott Hughes// kernel. 84913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause#define MAX_USBFS_BULK_SIZE (16 * 1024) 85913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause 865ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazaustruct usb_handle 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char fname[64]; 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int desc; 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_in; 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_out; 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 940b156638307db890e5539b52521fd24beb3440cbDavid Pursellclass LinuxUsbTransport : public Transport { 950b156638307db890e5539b52521fd24beb3440cbDavid Pursell public: 961c563d96f000876d77b2d33fbfb03c241bc503e1Chih-Hung Hsieh explicit LinuxUsbTransport(std::unique_ptr<usb_handle> handle) : handle_(std::move(handle)) {} 970b156638307db890e5539b52521fd24beb3440cbDavid Pursell ~LinuxUsbTransport() override = default; 980b156638307db890e5539b52521fd24beb3440cbDavid Pursell 990b156638307db890e5539b52521fd24beb3440cbDavid Pursell ssize_t Read(void* data, size_t len) override; 1000b156638307db890e5539b52521fd24beb3440cbDavid Pursell ssize_t Write(const void* data, size_t len) override; 1010b156638307db890e5539b52521fd24beb3440cbDavid Pursell int Close() override; 1020b156638307db890e5539b52521fd24beb3440cbDavid Pursell int WaitForDisconnect() override; 1030b156638307db890e5539b52521fd24beb3440cbDavid Pursell 1040b156638307db890e5539b52521fd24beb3440cbDavid Pursell private: 1050b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> handle_; 1060b156638307db890e5539b52521fd24beb3440cbDavid Pursell 1070b156638307db890e5539b52521fd24beb3440cbDavid Pursell DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport); 1080b156638307db890e5539b52521fd24beb3440cbDavid Pursell}; 1090b156638307db890e5539b52521fd24beb3440cbDavid Pursell 110bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler/* True if name isn't a valid name for a USB device in /sys/bus/usb/devices. 111bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * Device names are made up of numbers, dots, and dashes, e.g., '7-1.5'. 112bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * We reject interfaces (e.g., '7-1.5:1.0') and host controllers (e.g. 'usb1'). 113bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * The name must also start with a digit, to disallow '.' and '..' 114bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler */ 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int badname(const char *name) 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 117bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (!isdigit(*name)) 118bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 1; 119bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler while(*++name) { 120bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if(!isdigit(*name) && *name != '.' && *name != '-') 121bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 1; 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int check(void *_desc, int len, unsigned type, int size) 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 128aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)_desc; 1295ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len < size) return -1; 131aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bLength < size) return -1; 132aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bLength > len) return -1; 133aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(hdr->bDescriptorType != type) return -1; 1345ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 138157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachslerstatic int filter_usb_device(char* sysfs_name, 139bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char *ptr, int len, int writable, 140b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes ifc_match_func callback, 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int *ept_in_id, int *ept_out_id, int *ifc_id) 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_device_descriptor *dev; 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_config_descriptor *cfg; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_interface_descriptor *ifc; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_endpoint_descriptor *ept; 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_ifc_info info; 1485ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int in, out; 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned i; 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned e; 152588a2cad7faee54bfb16050d0c7398709f304feaJames Hawkins 153aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE)) 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 155aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin dev = (struct usb_device_descriptor *)ptr; 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= dev->bLength; 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += dev->bLength; 1585ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 159aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE)) 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 161aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin cfg = (struct usb_config_descriptor *)ptr; 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= cfg->bLength; 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += cfg->bLength; 1645ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_vendor = dev->idVendor; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_product = dev->idProduct; 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_class = dev->bDeviceClass; 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_subclass = dev->bDeviceSubClass; 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_protocol = dev->bDeviceProtocol; 170b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes info.writable = writable; 1715ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 172bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(info.device_path, sizeof(info.device_path), "usb:%s", sysfs_name); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 174bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler /* Read device serial number (if there is one). 175bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * We read the serial number from sysfs, since it's faster and more 176bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * reliable than issuing a control pipe read, and also won't 177bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * cause problems for devices which don't like getting descriptor 178bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * requests while they're in the middle of flashing. 17913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson */ 180bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[0] = '\0'; 181bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (dev->iSerialNumber) { 182bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char path[80]; 183bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int fd; 184bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 185bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(path, sizeof(path), 186bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler "/sys/bus/usb/devices/%s/serial", sysfs_name); 187bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler path[sizeof(path) - 1] = '\0'; 188bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 189bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler fd = open(path, O_RDONLY); 190bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (fd >= 0) { 191bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int chars_read = read(fd, info.serial_number, 192bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler sizeof(info.serial_number) - 1); 193bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler close(fd); 194bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 195bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (chars_read <= 0) 196bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[0] = '\0'; 197bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler else if (info.serial_number[chars_read - 1] == '\n') { 198bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler // strip trailing newline 199bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler info.serial_number[chars_read - 1] = '\0'; 200bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler } 20113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 20213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 20313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(i = 0; i < cfg->bNumInterfaces; i++) { 205aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 206aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin while (len > 0) { 207aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr; 208aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(hdr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE) == 0) 209aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 210aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin len -= hdr->bLength; 211aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ptr += hdr->bLength; 212aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 213aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 214aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (len <= 0) 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 216aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 217aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ifc = (struct usb_interface_descriptor *)ptr; 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ifc->bLength; 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ifc->bLength; 2205ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = -1; 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = -1; 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_class = ifc->bInterfaceClass; 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_subclass = ifc->bInterfaceSubClass; 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_protocol = ifc->bInterfaceProtocol; 2265ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(e = 0; e < ifc->bNumEndpoints; e++) { 228aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin while (len > 0) { 229aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr; 230aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (check(hdr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE) == 0) 231aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 232aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin len -= hdr->bLength; 233aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ptr += hdr->bLength; 234aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 235aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if (len < 0) { 236aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin break; 237aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin } 238aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin 239aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin ept = (struct usb_endpoint_descriptor *)ptr; 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ept->bLength; 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ept->bLength; 2425ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 243aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if((ept->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK) 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 2455ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 246aac89db8a541f609d8268966f7b3ded44da03bd1Patrick Tjin if(ept->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = ept->bEndpointAddress; 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = ept->bEndpointAddress; 250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 2511c02213e89f99c6f532b27048feb8f3170cac296Jack Pham 2521c02213e89f99c6f532b27048feb8f3170cac296Jack Pham // For USB 3.0 devices skip the SS Endpoint Companion descriptor 2531c02213e89f99c6f532b27048feb8f3170cac296Jack Pham if (check((struct usb_descriptor_hdr *)ptr, len, 2541c02213e89f99c6f532b27048feb8f3170cac296Jack Pham USB_DT_SS_ENDPOINT_COMP, USB_DT_SS_EP_COMP_SIZE) == 0) { 2551c02213e89f99c6f532b27048feb8f3170cac296Jack Pham len -= USB_DT_SS_EP_COMP_SIZE; 2561c02213e89f99c6f532b27048feb8f3170cac296Jack Pham ptr += USB_DT_SS_EP_COMP_SIZE; 2571c02213e89f99c6f532b27048feb8f3170cac296Jack Pham } 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_in = (in != -1); 261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_out = (out != -1); 2625ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(callback(&info) == 0) { 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_in_id = in; 265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_out_id = out; 266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ifc_id = ifc->bInterfaceNumber; 267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 274bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int read_sysfs_string(const char *sysfs_name, const char *sysfs_node, 275bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char* buf, int bufsize) 276bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 277bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char path[80]; 278bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int fd, n; 279bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 280bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(path, sizeof(path), 281bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler "/sys/bus/usb/devices/%s/%s", sysfs_name, sysfs_node); 282bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler path[sizeof(path) - 1] = '\0'; 283bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 284bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler fd = open(path, O_RDONLY); 285bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (fd < 0) 286bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 287bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 288bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler n = read(fd, buf, bufsize - 1); 289bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler close(fd); 290bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 291bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (n < 0) 292bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 293bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 294bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler buf[n] = '\0'; 295bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 296bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return n; 297bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 298bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 299bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int read_sysfs_number(const char *sysfs_name, const char *sysfs_node) 300bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 301bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char buf[16]; 302bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int value; 303bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 304bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (read_sysfs_string(sysfs_name, sysfs_node, buf, sizeof(buf)) < 0) 305bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 306bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 307bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (sscanf(buf, "%d", &value) != 1) 308bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 309bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 310bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return value; 311bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 312bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 313bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler/* Given the name of a USB device in sysfs, get the name for the same 314bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler * device in devfs. Returns 0 for success, -1 for failure. 315bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler */ 316bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachslerstatic int convert_to_devfs_name(const char* sysfs_name, 317bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char* devname, int devname_size) 318bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler{ 319bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler int busnum, devnum; 320bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 321bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler busnum = read_sysfs_number(sysfs_name, "busnum"); 322bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (busnum < 0) 323bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 324bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 325bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler devnum = read_sysfs_number(sysfs_name, "devnum"); 326bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler if (devnum < 0) 327bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return -1; 328bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 329bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler snprintf(devname, devname_size, "/dev/bus/usb/%03d/%03d", busnum, devnum); 330bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler return 0; 331bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler} 332bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler 3330b156638307db890e5539b52521fd24beb3440cbDavid Pursellstatic std::unique_ptr<usb_handle> find_usb_device(const char* base, ifc_match_func callback) 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 3350b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> usb; 336bd446c76f3676b1a8d752fbd83846b54a81ac602Mark Wachsler char devname[64]; 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char desc[1024]; 338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n, in, out, ifc; 3395ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 342c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes int writable; 3435ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 344588a2cad7faee54bfb16050d0c7398709f304feaJames Hawkins std::unique_ptr<DIR, decltype(&closedir)> busdir(opendir(base), closedir); 3450b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (busdir == 0) return 0; 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 347588a2cad7faee54bfb16050d0c7398709f304feaJames Hawkins while ((de = readdir(busdir.get())) && (usb == nullptr)) { 3480b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (badname(de->d_name)) continue; 3495ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 3500b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { 351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// DBG("[ scanning %s ]\n", devname); 353c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes writable = 1; 3540b156638307db890e5539b52521fd24beb3440cbDavid Pursell if ((fd = open(devname, O_RDWR)) < 0) { 355b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // Check if we have read-only access, so we can give a helpful 356b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // diagnostic like "adb devices" does. 357b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes writable = 0; 3580b156638307db890e5539b52521fd24beb3440cbDavid Pursell if ((fd = open(devname, O_RDONLY)) < 0) { 359b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes continue; 360b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes } 361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = read(fd, desc, sizeof(desc)); 3645ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 3650b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (filter_usb_device(de->d_name, desc, n, writable, callback, &in, &out, &ifc) == 0) { 3660b156638307db890e5539b52521fd24beb3440cbDavid Pursell usb.reset(new usb_handle()); 367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(usb->fname, devname); 368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_in = in; 369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_out = out; 370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->desc = fd; 371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); 3730b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (n != 0) { 374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 3750b156638307db890e5539b52521fd24beb3440cbDavid Pursell usb.reset(); 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return usb; 385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3870b156638307db890e5539b52521fd24beb3440cbDavid Pursellssize_t LinuxUsbTransport::Write(const void* _data, size_t len) 388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 3940b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (handle_->ep_out == 0 || handle_->desc == -1) { 395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3975ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 398157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler do { 399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int xfer; 400913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 4015ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4020b156638307db890e5539b52521fd24beb3440cbDavid Pursell bulk.ep = handle_->ep_out; 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 4065ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4070b156638307db890e5539b52521fd24beb3440cbDavid Pursell n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); 408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != xfer) { 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("ERROR: n = %d, errno = %d (%s)\n", 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n, errno, strerror(errno)); 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += xfer; 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= xfer; 416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += xfer; 417157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler } while(len > 0); 418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4220b156638307db890e5539b52521fd24beb3440cbDavid Pursellssize_t LinuxUsbTransport::Read(void* _data, size_t len) 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 427b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy int n, retry; 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4290b156638307db890e5539b52521fd24beb3440cbDavid Pursell if (handle_->ep_in == 0 || handle_->desc == -1) { 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4325ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 433290a228fdca935ab2e702db77516758314900c3aElliott Hughes while (len > 0) { 434913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 4355ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4360b156638307db890e5539b52521fd24beb3440cbDavid Pursell bulk.ep = handle_->ep_in; 437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 440b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy retry = 0; 441b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 442290a228fdca935ab2e702db77516758314900c3aElliott Hughes do { 443290a228fdca935ab2e702db77516758314900c3aElliott Hughes DBG("[ usb read %d fd = %d], fname=%s\n", xfer, handle_->desc, handle_->fname); 444290a228fdca935ab2e702db77516758314900c3aElliott Hughes n = ioctl(handle_->desc, USBDEVFS_BULK, &bulk); 445290a228fdca935ab2e702db77516758314900c3aElliott Hughes DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, handle_->fname, retry); 446b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 447290a228fdca935ab2e702db77516758314900c3aElliott Hughes if (n < 0) { 448290a228fdca935ab2e702db77516758314900c3aElliott Hughes DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno)); 449290a228fdca935ab2e702db77516758314900c3aElliott Hughes if (++retry > MAX_RETRIES) return -1; 450290a228fdca935ab2e702db77516758314900c3aElliott Hughes std::this_thread::sleep_for(1s); 451290a228fdca935ab2e702db77516758314900c3aElliott Hughes } 452290a228fdca935ab2e702db77516758314900c3aElliott Hughes } while (n < 0); 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += n; 455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= n; 456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += n; 4575ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < xfer) { 459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4625ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4660b156638307db890e5539b52521fd24beb3440cbDavid Pursellint LinuxUsbTransport::Close() 467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 4695ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 4700b156638307db890e5539b52521fd24beb3440cbDavid Pursell fd = handle_->desc; 4710b156638307db890e5539b52521fd24beb3440cbDavid Pursell handle_->desc = -1; 472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd >= 0) { 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("[ usb closed %d ]\n", fd); 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4800b156638307db890e5539b52521fd24beb3440cbDavid PursellTransport* usb_open(ifc_match_func callback) 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 4820b156638307db890e5539b52521fd24beb3440cbDavid Pursell std::unique_ptr<usb_handle> handle = find_usb_device("/sys/bus/usb/devices", callback); 4830b156638307db890e5539b52521fd24beb3440cbDavid Pursell return handle ? new LinuxUsbTransport(std::move(handle)) : nullptr; 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 485157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler 486157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler/* Wait for the system to notice the device is gone, so that a subsequent 487157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * fastboot command won't try to access the device before it's rebooted. 488157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler * Returns 0 for success, -1 for timeout. 489157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler */ 4900b156638307db890e5539b52521fd24beb3440cbDavid Pursellint LinuxUsbTransport::WaitForDisconnect() 491157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler{ 492157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler double deadline = now() + WAIT_FOR_DISCONNECT_TIMEOUT; 493157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler while (now() < deadline) { 494290a228fdca935ab2e702db77516758314900c3aElliott Hughes if (access(handle_->fname, F_OK)) return 0; 495290a228fdca935ab2e702db77516758314900c3aElliott Hughes std::this_thread::sleep_for(50ms); 496157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler } 497157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler return -1; 498157b00171a06f9ac2fd25ee3a86e801e896713d6Mark Wachsler} 499