Home | History | Annotate | Download | only in fastboot
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 #include <unistd.h>
     32 #include <string.h>
     33 
     34 #include <sys/ioctl.h>
     35 #include <sys/stat.h>
     36 #include <sys/types.h>
     37 #include <dirent.h>
     38 #include <fcntl.h>
     39 #include <errno.h>
     40 #include <pthread.h>
     41 #include <ctype.h>
     42 
     43 #include <linux/usbdevice_fs.h>
     44 #include <linux/usbdevice_fs.h>
     45 #include <linux/version.h>
     46 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20)
     47 #include <linux/usb/ch9.h>
     48 #else
     49 #include <linux/usb_ch9.h>
     50 #endif
     51 #include <asm/byteorder.h>
     52 
     53 #include "usb.h"
     54 
     55 #define MAX_RETRIES 5
     56 
     57 #ifdef TRACE_USB
     58 #define DBG1(x...) fprintf(stderr, x)
     59 #define DBG(x...) fprintf(stderr, x)
     60 #else
     61 #define DBG(x...)
     62 #define DBG1(x...)
     63 #endif
     64 
     65 /* The max bulk size for linux is 16384 which is defined
     66  * in drivers/usb/core/devio.c.
     67  */
     68 #define MAX_USBFS_BULK_SIZE (16 * 1024)
     69 
     70 struct usb_handle
     71 {
     72     char fname[64];
     73     int desc;
     74     unsigned char ep_in;
     75     unsigned char ep_out;
     76 };
     77 
     78 static inline int badname(const char *name)
     79 {
     80     while(*name) {
     81         if(!isdigit(*name++)) return 1;
     82     }
     83     return 0;
     84 }
     85 
     86 static int check(void *_desc, int len, unsigned type, int size)
     87 {
     88     unsigned char *desc = _desc;
     89 
     90     if(len < size) return -1;
     91     if(desc[0] < size) return -1;
     92     if(desc[0] > len) return -1;
     93     if(desc[1] != type) return -1;
     94 
     95     return 0;
     96 }
     97 
     98 static int filter_usb_device(int fd, char *ptr, int len, int writable,
     99                              ifc_match_func callback,
    100                              int *ept_in_id, int *ept_out_id, int *ifc_id)
    101 {
    102     struct usb_device_descriptor *dev;
    103     struct usb_config_descriptor *cfg;
    104     struct usb_interface_descriptor *ifc;
    105     struct usb_endpoint_descriptor *ept;
    106     struct usb_ifc_info info;
    107 
    108     int in, out;
    109     unsigned i;
    110     unsigned e;
    111 
    112     struct stat st;
    113     int result;
    114 
    115     if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
    116         return -1;
    117     dev = (void*) ptr;
    118     len -= dev->bLength;
    119     ptr += dev->bLength;
    120 
    121     if(check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE))
    122         return -1;
    123     cfg = (void*) ptr;
    124     len -= cfg->bLength;
    125     ptr += cfg->bLength;
    126 
    127     info.dev_vendor = dev->idVendor;
    128     info.dev_product = dev->idProduct;
    129     info.dev_class = dev->bDeviceClass;
    130     info.dev_subclass = dev->bDeviceSubClass;
    131     info.dev_protocol = dev->bDeviceProtocol;
    132     info.writable = writable;
    133 
    134     // read device serial number (if there is one)
    135     info.serial_number[0] = 0;
    136     if (dev->iSerialNumber) {
    137         struct usbdevfs_ctrltransfer  ctrl;
    138         // Keep it short enough because some bootloaders are borked if the URB len is > 255
    139         // 128 is too big by 1.
    140         __u16 buffer[127];
    141 
    142         memset(buffer, 0, sizeof(buffer));
    143 
    144         ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE;
    145         ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
    146         ctrl.wValue = (USB_DT_STRING << 8) | dev->iSerialNumber;
    147         //language ID (en-us) for serial number string
    148         ctrl.wIndex = 0x0409;
    149         ctrl.wLength = sizeof(buffer);
    150         ctrl.data = buffer;
    151         ctrl.timeout = 50;
    152 
    153         result = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
    154         if (result > 0) {
    155             int i;
    156             // skip first word, and copy the rest to the serial string, changing shorts to bytes.
    157             result /= 2;
    158             for (i = 1; i < result; i++)
    159                 info.serial_number[i - 1] = buffer[i];
    160             info.serial_number[i - 1] = 0;
    161         }
    162     }
    163 
    164     /* We need to get a path that represents a particular port on a particular
    165      * hub.  We are passed an fd that was obtained by opening an entry under
    166      * /dev/bus/usb.  Unfortunately, the names of those entries change each
    167      * time devices are plugged and unplugged.  So how to get a repeatable
    168      * path?  udevadm provided the inspiration.  We can get the major and
    169      * minor of the device file, read the symlink that can be found here:
    170      *   /sys/dev/char/<major>:<minor>
    171      * and then use the last element of that path.  As a concrete example, I
    172      * have an Android device at /dev/bus/usb/001/027 so working with bash:
    173      *   $ ls -l /dev/bus/usb/001/027
    174      *   crw-rw-r-- 1 root plugdev 189, 26 Apr  9 11:03 /dev/bus/usb/001/027
    175      *   $ ls -l /sys/dev/char/189:26
    176      *   lrwxrwxrwx 1 root root 0 Apr  9 11:03 /sys/dev/char/189:26 ->
    177      *           ../../devices/pci0000:00/0000:00:1a.7/usb1/1-4/1-4.2/1-4.2.3
    178      * So our device_path would be 1-4.2.3 which says my device is connected
    179      * to port 3 of a hub on port 2 of a hub on port 4 of bus 1 (per
    180      * http://www.linux-usb.org/FAQ.html).
    181      */
    182     info.device_path[0] = '\0';
    183     result = fstat(fd, &st);
    184     if (!result && S_ISCHR(st.st_mode)) {
    185         char cdev[128];
    186         char link[256];
    187         char *slash;
    188         ssize_t link_len;
    189         snprintf(cdev, sizeof(cdev), "/sys/dev/char/%d:%d",
    190                  major(st.st_rdev), minor(st.st_rdev));
    191         link_len = readlink(cdev, link, sizeof(link) - 1);
    192         if (link_len > 0) {
    193             link[link_len] = '\0';
    194             slash = strrchr(link, '/');
    195             if (slash)
    196                 snprintf(info.device_path, sizeof(info.device_path), "usb:%s", slash+1);
    197         }
    198     }
    199 
    200     for(i = 0; i < cfg->bNumInterfaces; i++) {
    201         if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE))
    202             return -1;
    203         ifc = (void*) ptr;
    204         len -= ifc->bLength;
    205         ptr += ifc->bLength;
    206 
    207         in = -1;
    208         out = -1;
    209         info.ifc_class = ifc->bInterfaceClass;
    210         info.ifc_subclass = ifc->bInterfaceSubClass;
    211         info.ifc_protocol = ifc->bInterfaceProtocol;
    212 
    213         for(e = 0; e < ifc->bNumEndpoints; e++) {
    214             if(check(ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE))
    215                 return -1;
    216             ept = (void*) ptr;
    217             len -= ept->bLength;
    218             ptr += ept->bLength;
    219 
    220             if((ept->bmAttributes & 0x03) != 0x02)
    221                 continue;
    222 
    223             if(ept->bEndpointAddress & 0x80) {
    224                 in = ept->bEndpointAddress;
    225             } else {
    226                 out = ept->bEndpointAddress;
    227             }
    228         }
    229 
    230         info.has_bulk_in = (in != -1);
    231         info.has_bulk_out = (out != -1);
    232 
    233         if(callback(&info) == 0) {
    234             *ept_in_id = in;
    235             *ept_out_id = out;
    236             *ifc_id = ifc->bInterfaceNumber;
    237             return 0;
    238         }
    239     }
    240 
    241     return -1;
    242 }
    243 
    244 static usb_handle *find_usb_device(const char *base, ifc_match_func callback)
    245 {
    246     usb_handle *usb = 0;
    247     char busname[64], devname[64];
    248     char desc[1024];
    249     int n, in, out, ifc;
    250 
    251     DIR *busdir, *devdir;
    252     struct dirent *de;
    253     int fd;
    254     int writable;
    255 
    256     busdir = opendir(base);
    257     if(busdir == 0) return 0;
    258 
    259     while((de = readdir(busdir)) && (usb == 0)) {
    260         if(badname(de->d_name)) continue;
    261 
    262         sprintf(busname, "%s/%s", base, de->d_name);
    263         devdir = opendir(busname);
    264         if(devdir == 0) continue;
    265 
    266 //        DBG("[ scanning %s ]\n", busname);
    267         while((de = readdir(devdir)) && (usb == 0)) {
    268 
    269             if(badname(de->d_name)) continue;
    270             sprintf(devname, "%s/%s", busname, de->d_name);
    271 
    272 //            DBG("[ scanning %s ]\n", devname);
    273             writable = 1;
    274             if((fd = open(devname, O_RDWR)) < 0) {
    275                 // Check if we have read-only access, so we can give a helpful
    276                 // diagnostic like "adb devices" does.
    277                 writable = 0;
    278                 if((fd = open(devname, O_RDONLY)) < 0) {
    279                     continue;
    280                 }
    281             }
    282 
    283             n = read(fd, desc, sizeof(desc));
    284 
    285             if(filter_usb_device(fd, desc, n, writable, callback,
    286                                  &in, &out, &ifc) == 0) {
    287                 usb = calloc(1, sizeof(usb_handle));
    288                 strcpy(usb->fname, devname);
    289                 usb->ep_in = in;
    290                 usb->ep_out = out;
    291                 usb->desc = fd;
    292 
    293                 n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc);
    294                 if(n != 0) {
    295                     close(fd);
    296                     free(usb);
    297                     usb = 0;
    298                     continue;
    299                 }
    300             } else {
    301                 close(fd);
    302             }
    303         }
    304         closedir(devdir);
    305     }
    306     closedir(busdir);
    307 
    308     return usb;
    309 }
    310 
    311 int usb_write(usb_handle *h, const void *_data, int len)
    312 {
    313     unsigned char *data = (unsigned char*) _data;
    314     unsigned count = 0;
    315     struct usbdevfs_bulktransfer bulk;
    316     int n;
    317 
    318     if(h->ep_out == 0) {
    319         return -1;
    320     }
    321 
    322     if(len == 0) {
    323         bulk.ep = h->ep_out;
    324         bulk.len = 0;
    325         bulk.data = data;
    326         bulk.timeout = 0;
    327 
    328         n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
    329         if(n != 0) {
    330             fprintf(stderr,"ERROR: n = %d, errno = %d (%s)\n",
    331                     n, errno, strerror(errno));
    332             return -1;
    333         }
    334         return 0;
    335     }
    336 
    337     while(len > 0) {
    338         int xfer;
    339         xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
    340 
    341         bulk.ep = h->ep_out;
    342         bulk.len = xfer;
    343         bulk.data = data;
    344         bulk.timeout = 0;
    345 
    346         n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
    347         if(n != xfer) {
    348             DBG("ERROR: n = %d, errno = %d (%s)\n",
    349                 n, errno, strerror(errno));
    350             return -1;
    351         }
    352 
    353         count += xfer;
    354         len -= xfer;
    355         data += xfer;
    356     }
    357 
    358     return count;
    359 }
    360 
    361 int usb_read(usb_handle *h, void *_data, int len)
    362 {
    363     unsigned char *data = (unsigned char*) _data;
    364     unsigned count = 0;
    365     struct usbdevfs_bulktransfer bulk;
    366     int n, retry;
    367 
    368     if(h->ep_in == 0) {
    369         return -1;
    370     }
    371 
    372     while(len > 0) {
    373         int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
    374 
    375         bulk.ep = h->ep_in;
    376         bulk.len = xfer;
    377         bulk.data = data;
    378         bulk.timeout = 0;
    379         retry = 0;
    380 
    381         do{
    382            DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname);
    383            n = ioctl(h->desc, USBDEVFS_BULK, &bulk);
    384            DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry);
    385 
    386            if( n < 0 ) {
    387             DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno));
    388             if ( ++retry > MAX_RETRIES ) return -1;
    389             sleep( 1 );
    390            }
    391         }
    392         while( n < 0 );
    393 
    394         count += n;
    395         len -= n;
    396         data += n;
    397 
    398         if(n < xfer) {
    399             break;
    400         }
    401     }
    402 
    403     return count;
    404 }
    405 
    406 void usb_kick(usb_handle *h)
    407 {
    408     int fd;
    409 
    410     fd = h->desc;
    411     h->desc = -1;
    412     if(fd >= 0) {
    413         close(fd);
    414         DBG("[ usb closed %d ]\n", fd);
    415     }
    416 }
    417 
    418 int usb_close(usb_handle *h)
    419 {
    420     int fd;
    421 
    422     fd = h->desc;
    423     h->desc = -1;
    424     if(fd >= 0) {
    425         close(fd);
    426         DBG("[ usb closed %d ]\n", fd);
    427     }
    428 
    429     return 0;
    430 }
    431 
    432 usb_handle *usb_open(ifc_match_func callback)
    433 {
    434     return find_usb_device("/dev/bus/usb", callback);
    435 }
    436