usb_linux.c revision bd446c76f3676b1a8d752fbd83846b54a81ac602
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 70struct usb_handle 71{ 72 char fname[64]; 73 int desc; 74 unsigned char ep_in; 75 unsigned char ep_out; 76}; 77 78/* True if name isn't a valid name for a USB device in /sys/bus/usb/devices. 79 * Device names are made up of numbers, dots, and dashes, e.g., '7-1.5'. 80 * We reject interfaces (e.g., '7-1.5:1.0') and host controllers (e.g. 'usb1'). 81 * The name must also start with a digit, to disallow '.' and '..' 82 */ 83static inline int badname(const char *name) 84{ 85 if (!isdigit(*name)) 86 return 1; 87 while(*++name) { 88 if(!isdigit(*name) && *name != '.' && *name != '-') 89 return 1; 90 } 91 return 0; 92} 93 94static int check(void *_desc, int len, unsigned type, int size) 95{ 96 unsigned char *desc = _desc; 97 98 if(len < size) return -1; 99 if(desc[0] < size) return -1; 100 if(desc[0] > len) return -1; 101 if(desc[1] != type) return -1; 102 103 return 0; 104} 105 106static int filter_usb_device(int fd, char* sysfs_name, 107 char *ptr, int len, int writable, 108 ifc_match_func callback, 109 int *ept_in_id, int *ept_out_id, int *ifc_id) 110{ 111 struct usb_device_descriptor *dev; 112 struct usb_config_descriptor *cfg; 113 struct usb_interface_descriptor *ifc; 114 struct usb_endpoint_descriptor *ept; 115 struct usb_ifc_info info; 116 117 int in, out; 118 unsigned i; 119 unsigned e; 120 121 struct stat st; 122 int result; 123 124 if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE)) 125 return -1; 126 dev = (void*) ptr; 127 len -= dev->bLength; 128 ptr += dev->bLength; 129 130 if(check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE)) 131 return -1; 132 cfg = (void*) ptr; 133 len -= cfg->bLength; 134 ptr += cfg->bLength; 135 136 info.dev_vendor = dev->idVendor; 137 info.dev_product = dev->idProduct; 138 info.dev_class = dev->bDeviceClass; 139 info.dev_subclass = dev->bDeviceSubClass; 140 info.dev_protocol = dev->bDeviceProtocol; 141 info.writable = writable; 142 143 snprintf(info.device_path, sizeof(info.device_path), "usb:%s", sysfs_name); 144 145 /* Read device serial number (if there is one). 146 * We read the serial number from sysfs, since it's faster and more 147 * reliable than issuing a control pipe read, and also won't 148 * cause problems for devices which don't like getting descriptor 149 * requests while they're in the middle of flashing. 150 */ 151 info.serial_number[0] = '\0'; 152 if (dev->iSerialNumber) { 153 char path[80]; 154 int fd; 155 156 snprintf(path, sizeof(path), 157 "/sys/bus/usb/devices/%s/serial", sysfs_name); 158 path[sizeof(path) - 1] = '\0'; 159 160 fd = open(path, O_RDONLY); 161 if (fd >= 0) { 162 int chars_read = read(fd, info.serial_number, 163 sizeof(info.serial_number) - 1); 164 close(fd); 165 166 if (chars_read <= 0) 167 info.serial_number[0] = '\0'; 168 else if (info.serial_number[chars_read - 1] == '\n') { 169 // strip trailing newline 170 info.serial_number[chars_read - 1] = '\0'; 171 } 172 } 173 } 174 175 for(i = 0; i < cfg->bNumInterfaces; i++) { 176 if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE)) 177 return -1; 178 ifc = (void*) ptr; 179 len -= ifc->bLength; 180 ptr += ifc->bLength; 181 182 in = -1; 183 out = -1; 184 info.ifc_class = ifc->bInterfaceClass; 185 info.ifc_subclass = ifc->bInterfaceSubClass; 186 info.ifc_protocol = ifc->bInterfaceProtocol; 187 188 for(e = 0; e < ifc->bNumEndpoints; e++) { 189 if(check(ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE)) 190 return -1; 191 ept = (void*) ptr; 192 len -= ept->bLength; 193 ptr += ept->bLength; 194 195 if((ept->bmAttributes & 0x03) != 0x02) 196 continue; 197 198 if(ept->bEndpointAddress & 0x80) { 199 in = ept->bEndpointAddress; 200 } else { 201 out = ept->bEndpointAddress; 202 } 203 } 204 205 info.has_bulk_in = (in != -1); 206 info.has_bulk_out = (out != -1); 207 208 if(callback(&info) == 0) { 209 *ept_in_id = in; 210 *ept_out_id = out; 211 *ifc_id = ifc->bInterfaceNumber; 212 return 0; 213 } 214 } 215 216 return -1; 217} 218 219static int read_sysfs_string(const char *sysfs_name, const char *sysfs_node, 220 char* buf, int bufsize) 221{ 222 char path[80]; 223 int fd, n; 224 225 snprintf(path, sizeof(path), 226 "/sys/bus/usb/devices/%s/%s", sysfs_name, sysfs_node); 227 path[sizeof(path) - 1] = '\0'; 228 229 fd = open(path, O_RDONLY); 230 if (fd < 0) 231 return -1; 232 233 n = read(fd, buf, bufsize - 1); 234 close(fd); 235 236 if (n < 0) 237 return -1; 238 239 buf[n] = '\0'; 240 241 return n; 242} 243 244static int read_sysfs_number(const char *sysfs_name, const char *sysfs_node) 245{ 246 char buf[16]; 247 int value; 248 249 if (read_sysfs_string(sysfs_name, sysfs_node, buf, sizeof(buf)) < 0) 250 return -1; 251 252 if (sscanf(buf, "%d", &value) != 1) 253 return -1; 254 255 return value; 256} 257 258/* Given the name of a USB device in sysfs, get the name for the same 259 * device in devfs. Returns 0 for success, -1 for failure. 260 */ 261static int convert_to_devfs_name(const char* sysfs_name, 262 char* devname, int devname_size) 263{ 264 int busnum, devnum; 265 266 busnum = read_sysfs_number(sysfs_name, "busnum"); 267 if (busnum < 0) 268 return -1; 269 270 devnum = read_sysfs_number(sysfs_name, "devnum"); 271 if (devnum < 0) 272 return -1; 273 274 snprintf(devname, devname_size, "/dev/bus/usb/%03d/%03d", busnum, devnum); 275 return 0; 276} 277 278static usb_handle *find_usb_device(const char *base, ifc_match_func callback) 279{ 280 usb_handle *usb = 0; 281 char devname[64]; 282 char desc[1024]; 283 int n, in, out, ifc; 284 285 DIR *busdir; 286 struct dirent *de; 287 int fd; 288 int writable; 289 290 busdir = opendir(base); 291 if(busdir == 0) return 0; 292 293 while((de = readdir(busdir)) && (usb == 0)) { 294 if(badname(de->d_name)) continue; 295 296 if(!convert_to_devfs_name(de->d_name, devname, sizeof(devname))) { 297 298// DBG("[ scanning %s ]\n", devname); 299 writable = 1; 300 if((fd = open(devname, O_RDWR)) < 0) { 301 // Check if we have read-only access, so we can give a helpful 302 // diagnostic like "adb devices" does. 303 writable = 0; 304 if((fd = open(devname, O_RDONLY)) < 0) { 305 continue; 306 } 307 } 308 309 n = read(fd, desc, sizeof(desc)); 310 311 if(filter_usb_device(fd, de->d_name, desc, n, writable, callback, 312 &in, &out, &ifc) == 0) { 313 usb = calloc(1, sizeof(usb_handle)); 314 strcpy(usb->fname, devname); 315 usb->ep_in = in; 316 usb->ep_out = out; 317 usb->desc = fd; 318 319 n = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &ifc); 320 if(n != 0) { 321 close(fd); 322 free(usb); 323 usb = 0; 324 continue; 325 } 326 } else { 327 close(fd); 328 } 329 } 330 } 331 closedir(busdir); 332 333 return usb; 334} 335 336int usb_write(usb_handle *h, const void *_data, int len) 337{ 338 unsigned char *data = (unsigned char*) _data; 339 unsigned count = 0; 340 struct usbdevfs_bulktransfer bulk; 341 int n; 342 343 if(h->ep_out == 0) { 344 return -1; 345 } 346 347 if(len == 0) { 348 bulk.ep = h->ep_out; 349 bulk.len = 0; 350 bulk.data = data; 351 bulk.timeout = 0; 352 353 n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 354 if(n != 0) { 355 fprintf(stderr,"ERROR: n = %d, errno = %d (%s)\n", 356 n, errno, strerror(errno)); 357 return -1; 358 } 359 return 0; 360 } 361 362 while(len > 0) { 363 int xfer; 364 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 365 366 bulk.ep = h->ep_out; 367 bulk.len = xfer; 368 bulk.data = data; 369 bulk.timeout = 0; 370 371 n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 372 if(n != xfer) { 373 DBG("ERROR: n = %d, errno = %d (%s)\n", 374 n, errno, strerror(errno)); 375 return -1; 376 } 377 378 count += xfer; 379 len -= xfer; 380 data += xfer; 381 } 382 383 return count; 384} 385 386int usb_read(usb_handle *h, void *_data, int len) 387{ 388 unsigned char *data = (unsigned char*) _data; 389 unsigned count = 0; 390 struct usbdevfs_bulktransfer bulk; 391 int n, retry; 392 393 if(h->ep_in == 0) { 394 return -1; 395 } 396 397 while(len > 0) { 398 int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len; 399 400 bulk.ep = h->ep_in; 401 bulk.len = xfer; 402 bulk.data = data; 403 bulk.timeout = 0; 404 retry = 0; 405 406 do{ 407 DBG("[ usb read %d fd = %d], fname=%s\n", xfer, h->desc, h->fname); 408 n = ioctl(h->desc, USBDEVFS_BULK, &bulk); 409 DBG("[ usb read %d ] = %d, fname=%s, Retry %d \n", xfer, n, h->fname, retry); 410 411 if( n < 0 ) { 412 DBG1("ERROR: n = %d, errno = %d (%s)\n",n, errno, strerror(errno)); 413 if ( ++retry > MAX_RETRIES ) return -1; 414 sleep( 1 ); 415 } 416 } 417 while( n < 0 ); 418 419 count += n; 420 len -= n; 421 data += n; 422 423 if(n < xfer) { 424 break; 425 } 426 } 427 428 return count; 429} 430 431void usb_kick(usb_handle *h) 432{ 433 int fd; 434 435 fd = h->desc; 436 h->desc = -1; 437 if(fd >= 0) { 438 close(fd); 439 DBG("[ usb closed %d ]\n", fd); 440 } 441} 442 443int usb_close(usb_handle *h) 444{ 445 int fd; 446 447 fd = h->desc; 448 h->desc = -1; 449 if(fd >= 0) { 450 close(fd); 451 DBG("[ usb closed %d ]\n", fd); 452 } 453 454 return 0; 455} 456 457usb_handle *usb_open(ifc_match_func callback) 458{ 459 return find_usb_device("/sys/bus/usb/devices", callback); 460} 461