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 29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h> 30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h> 31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h> 32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h> 33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/ioctl.h> 3513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson#include <sys/stat.h> 36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h> 37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h> 38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h> 39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h> 40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <pthread.h> 41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h> 42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usbdevice_fs.h> 44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usbdevice_fs.h> 45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/version.h> 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usb/ch9.h> 48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/usb_ch9.h> 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <asm/byteorder.h> 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "usb.h" 54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 55b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#define MAX_RETRIES 5 56b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 57b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy#ifdef TRACE_USB 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) fprintf(stderr, x) 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) fprintf(stderr, x) 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG(x...) 62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DBG1(x...) 63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 65913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause/* The max bulk size for linux is 16384 which is defined 66913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause * in drivers/usb/core/devio.c. 67913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause */ 68913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause#define MAX_USBFS_BULK_SIZE (16 * 1024) 69913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause 705ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazaustruct usb_handle 71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char fname[64]; 73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int desc; 74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_in; 75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char ep_out; 76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}; 77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic inline int badname(const char *name) 79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(*name) { 81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(!isdigit(*name++)) return 1; 82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int check(void *_desc, int len, unsigned type, int size) 87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *desc = _desc; 895ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len < size) return -1; 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(desc[0] < size) return -1; 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(desc[0] > len) return -1; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(desc[1] != type) return -1; 945ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 98b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughesstatic int filter_usb_device(int fd, char *ptr, int len, int writable, 99b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes ifc_match_func callback, 100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int *ept_in_id, int *ept_out_id, int *ifc_id) 101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_device_descriptor *dev; 103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_config_descriptor *cfg; 104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_interface_descriptor *ifc; 105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_endpoint_descriptor *ept; 106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usb_ifc_info info; 1075ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int in, out; 109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned i; 110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned e; 111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 11213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson struct stat st; 11313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson int result; 1145ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE)) 116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project dev = (void*) ptr; 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= dev->bLength; 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += dev->bLength; 1205ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE)) 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project cfg = (void*) ptr; 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= cfg->bLength; 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += cfg->bLength; 1265ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_vendor = dev->idVendor; 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_product = dev->idProduct; 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_class = dev->bDeviceClass; 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_subclass = dev->bDeviceSubClass; 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.dev_protocol = dev->bDeviceProtocol; 132b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes info.writable = writable; 1335ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // read device serial number (if there is one) 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.serial_number[0] = 0; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (dev->iSerialNumber) { 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_ctrltransfer ctrl; 138f8ff3a5ae21ce34f22928709cc6f992ff2fdd56eJP Abgrall // Keep it short enough because some bootloaders are borked if the URB len is > 255 139f8ff3a5ae21ce34f22928709cc6f992ff2fdd56eJP Abgrall // 128 is too big by 1. 140f8ff3a5ae21ce34f22928709cc6f992ff2fdd56eJP Abgrall __u16 buffer[127]; 141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(buffer, 0, sizeof(buffer)); 143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ctrl.wValue = (USB_DT_STRING << 8) | dev->iSerialNumber; 147c840653efd8d05a33778d3e73c3521977564bde3mgross //language ID (en-us) for serial number string 148c840653efd8d05a33778d3e73c3521977564bde3mgross ctrl.wIndex = 0x0409; 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ctrl.wLength = sizeof(buffer); 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ctrl.data = buffer; 151c840653efd8d05a33778d3e73c3521977564bde3mgross ctrl.timeout = 50; 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result = ioctl(fd, USBDEVFS_CONTROL, &ctrl); 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (result > 0) { 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int i; 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project // skip first word, and copy the rest to the serial string, changing shorts to bytes. 157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result /= 2; 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (i = 1; i < result; i++) 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.serial_number[i - 1] = buffer[i]; 160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.serial_number[i - 1] = 0; 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 16413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson /* We need to get a path that represents a particular port on a particular 16513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * hub. We are passed an fd that was obtained by opening an entry under 16613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * /dev/bus/usb. Unfortunately, the names of those entries change each 16713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * time devices are plugged and unplugged. So how to get a repeatable 16813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * path? udevadm provided the inspiration. We can get the major and 16913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * minor of the device file, read the symlink that can be found here: 17013081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * /sys/dev/char/<major>:<minor> 17113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * and then use the last element of that path. As a concrete example, I 17213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * have an Android device at /dev/bus/usb/001/027 so working with bash: 17313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * $ ls -l /dev/bus/usb/001/027 17413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * crw-rw-r-- 1 root plugdev 189, 26 Apr 9 11:03 /dev/bus/usb/001/027 17513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * $ ls -l /sys/dev/char/189:26 17613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * lrwxrwxrwx 1 root root 0 Apr 9 11:03 /sys/dev/char/189:26 -> 17713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * ../../devices/pci0000:00/0000:00:1a.7/usb1/1-4/1-4.2/1-4.2.3 17813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * So our device_path would be 1-4.2.3 which says my device is connected 17913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * to port 3 of a hub on port 2 of a hub on port 4 of bus 1 (per 18013081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson * http://www.linux-usb.org/FAQ.html). 18113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson */ 18213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson info.device_path[0] = '\0'; 18313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson result = fstat(fd, &st); 18413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson if (!result && S_ISCHR(st.st_mode)) { 18513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson char cdev[128]; 18613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson char link[256]; 18713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson char *slash; 18813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson ssize_t link_len; 18913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson snprintf(cdev, sizeof(cdev), "/sys/dev/char/%d:%d", 19013081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson major(st.st_rdev), minor(st.st_rdev)); 19113081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson link_len = readlink(cdev, link, sizeof(link) - 1); 19213081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson if (link_len > 0) { 19313081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson link[link_len] = '\0'; 19413081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson slash = strrchr(link, '/'); 19513081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson if (slash) 19613081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson snprintf(info.device_path, sizeof(info.device_path), "usb:%s", slash+1); 19713081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 19813081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson } 19913081c6915220db03886b177f1a8e0b2c63467c9Scott Anderson 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(i = 0; i < cfg->bNumInterfaces; i++) { 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE)) 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc = (void*) ptr; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ifc->bLength; 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ifc->bLength; 2065ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = -1; 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = -1; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_class = ifc->bInterfaceClass; 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_subclass = ifc->bInterfaceSubClass; 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.ifc_protocol = ifc->bInterfaceProtocol; 2125ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for(e = 0; e < ifc->bNumEndpoints; e++) { 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(check(ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE)) 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ept = (void*) ptr; 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= ept->bLength; 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ptr += ept->bLength; 2195ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((ept->bmAttributes & 0x03) != 0x02) 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 2225ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ept->bEndpointAddress & 0x80) { 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in = ept->bEndpointAddress; 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project out = ept->bEndpointAddress; 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_in = (in != -1); 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project info.has_bulk_out = (out != -1); 2325ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(callback(&info) == 0) { 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_in_id = in; 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ept_out_id = out; 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *ifc_id = ifc->bInterfaceNumber; 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic usb_handle *find_usb_device(const char *base, ifc_match_func callback) 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb_handle *usb = 0; 247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char busname[64], devname[64]; 248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char desc[1024]; 249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n, in, out, ifc; 2505ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DIR *busdir, *devdir; 252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct dirent *de; 253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 254c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes int writable; 2555ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project busdir = opendir(base); 257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(busdir == 0) return 0; 258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while((de = readdir(busdir)) && (usb == 0)) { 260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(badname(de->d_name)) continue; 2615ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(busname, "%s/%s", base, de->d_name); 263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project devdir = opendir(busname); 264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(devdir == 0) continue; 2655ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// DBG("[ scanning %s ]\n", busname); 267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while((de = readdir(devdir)) && (usb == 0)) { 2685ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(badname(de->d_name)) continue; 270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sprintf(devname, "%s/%s", busname, de->d_name); 271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// DBG("[ scanning %s ]\n", devname); 273c500be926cf07c43aeb828ae86b04b856c6b7c63Elliott Hughes writable = 1; 274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if((fd = open(devname, O_RDWR)) < 0) { 275b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // Check if we have read-only access, so we can give a helpful 276b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes // diagnostic like "adb devices" does. 277b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes writable = 0; 278b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes if((fd = open(devname, O_RDONLY)) < 0) { 279b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes continue; 280b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes } 281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = read(fd, desc, sizeof(desc)); 2845ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 285b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes if(filter_usb_device(fd, desc, n, writable, callback, 286b4add9b74525210478bac702d27fdaf9cf7ab18fElliott Hughes &in, &out, &ifc) == 0) { 287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb = calloc(1, sizeof(usb_handle)); 288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strcpy(usb->fname, devname); 289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_in = in; 290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->ep_out = out; 291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb->desc = fd; 292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); 294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != 0) { 295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project free(usb); 297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project usb = 0; 298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(devdir); 305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project closedir(busdir); 307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return usb; 309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_write(usb_handle *h, const void *_data, int len) 312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int n; 317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(h->ep_out == 0) { 319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3215ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(len == 0) { 323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.ep = h->ep_out; 324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = 0; 325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 3275ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != 0) { 330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fprintf(stderr,"ERROR: n = %d, errno = %d (%s)\n", 331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n, errno, strerror(errno)); 332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3365ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(len > 0) { 338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int xfer; 339913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 3405ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.ep = h->ep_out; 342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 3455ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n != xfer) { 348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("ERROR: n = %d, errno = %d (%s)\n", 349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project n, errno, strerror(errno)); 350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += xfer; 354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= xfer; 355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += xfer; 356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_read(usb_handle *h, void *_data, int len) 362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned char *data = (unsigned char*) _data; 364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project unsigned count = 0; 365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct usbdevfs_bulktransfer bulk; 366b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy int n, retry; 367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(h->ep_in == 0) { 369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 3715ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project while(len > 0) { 373913eb8bf874fcec647667bd7113da65b6e38488aDavid Krause int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 3745ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.ep = h->ep_in; 376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.len = xfer; 377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.data = data; 378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project bulk.timeout = 0; 379b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy retry = 0; 380b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 381b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy do{ 382b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); 383b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 384b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry); 385b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy 386b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy if( n < 0 ) { 387b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno)); 388b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy if ( ++retry > MAX_RETRIES ) return -1; 389b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy sleep( 1 ); 390b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy } 391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 392b2de4db941f5329f9f19e70feff5786b2d5acbb6Dan Murphy while( n < 0 ); 393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project count += n; 395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project len -= n; 396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project data += n; 3975ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(n < xfer) { 399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4025ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return count; 404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid usb_kick(usb_handle *h) 407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = h->desc; 411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->desc = -1; 412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd >= 0) { 413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("[ usb closed %d ]\n", fd); 415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint usb_close(usb_handle *h) 419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int fd; 4215ae3f93f3bafbeb1fc9a3324475c58c725749c5eAnatol Pomazau 422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fd = h->desc; 423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project h->desc = -1; 424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(fd >= 0) { 425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project close(fd); 426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project DBG("[ usb closed %d ]\n", fd); 427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectusb_handle *usb_open(ifc_match_func callback) 433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return find_usb_device("/dev/bus/usb", callback); 435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 436