usbhost.c revision 5e567cb34b5e54467f501fc9703db82ca6639ff3
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <unistd.h> 20#include <string.h> 21 22#include <sys/ioctl.h> 23#include <sys/types.h> 24#include <sys/time.h> 25#include <sys/inotify.h> 26#include <dirent.h> 27#include <fcntl.h> 28#include <errno.h> 29#include <ctype.h> 30#include <pthread.h> 31 32#include <linux/usbdevice_fs.h> 33#include <linux/version.h> 34#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) 35#include <linux/usb/ch9.h> 36#else 37#include <linux/usb_ch9.h> 38#endif 39#include <asm/byteorder.h> 40 41#include "usbhost/usbhost.h" 42 43#define USB_FS_DIR "/dev/bus/usb" 44 45#if 0 46#define D printf 47#else 48#define D(...) 49#endif 50 51struct usb_device { 52 char dev_name[64]; 53 unsigned char desc[256]; 54 int desc_length; 55 int fd; 56 int writeable; 57}; 58 59struct usb_endpoint 60{ 61 struct usb_device *dev; 62 struct usb_endpoint_descriptor desc; 63 struct usbdevfs_urb urb; 64}; 65 66static usb_device_added_cb s_added_cb; 67static usb_device_removed_cb s_removed_cb; 68 69static inline int badname(const char *name) 70{ 71 while(*name) { 72 if(!isdigit(*name++)) return 1; 73 } 74 return 0; 75} 76 77static void find_existing_devices() 78{ 79 char busname[32], devname[32]; 80 DIR *busdir , *devdir ; 81 struct dirent *de; 82 83 busdir = opendir(USB_FS_DIR); 84 if(busdir == 0) return; 85 86 while((de = readdir(busdir)) != 0) { 87 if(badname(de->d_name)) continue; 88 89 snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name); 90 devdir = opendir(busname); 91 if(devdir == 0) continue; 92 93 while((de = readdir(devdir))) { 94 if(badname(de->d_name)) continue; 95 96 snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); 97 s_added_cb(devname); 98 } // end of devdir while 99 closedir(devdir); 100 } //end of busdir while 101 closedir(busdir); 102} 103 104static void* device_discovery_thread(void* unused) 105{ 106 struct inotify_event* event; 107 char event_buf[512]; 108 char path[100]; 109 int i, fd, ret; 110 int wd, wds[10]; 111 int wd_count = sizeof(wds) / sizeof(wds[0]); 112 113 D("Created device discovery thread\n"); 114 115 fd = inotify_init(); 116 if (fd < 0) { 117 fprintf(stderr, "inotify_init failed\n"); 118 return NULL; 119 } 120 121 /* watch for files added and deleted within USB_FS_DIR */ 122 memset(wds, 0, sizeof(wds)); 123 /* watch the root for new subdirectories */ 124 wds[0] = inotify_add_watch(fd, USB_FS_DIR, IN_CREATE | IN_DELETE); 125 if (wds[0] < 0) { 126 fprintf(stderr, "inotify_add_watch failed\n"); 127 return NULL; 128 } 129 130 /* watch existing subdirectories of USB_FS_DIR */ 131 for (i = 1; i < wd_count; i++) { 132 snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i); 133 ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE); 134 if (ret > 0) 135 wds[i] = ret; 136 } 137 138 /* check for existing devices first, after we have inotify set up */ 139 if (s_added_cb) 140 find_existing_devices(); 141 142 while (1) { 143 ret = read(fd, event_buf, sizeof(event_buf)); 144 if (ret >= (int)sizeof(struct inotify_event)) { 145 event = (struct inotify_event *)event_buf; 146 wd = event->wd; 147 if (wd == wds[0]) { 148 i = atoi(event->name); 149 snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name); 150 D("new subdirectory %s: index: %d\n", path, i); 151 if (i > 0 && i < wd_count) { 152 ret = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE); 153 if (ret > 0) 154 wds[i] = ret; 155 } 156 } else { 157 for (i = 1; i < wd_count; i++) { 158 if (wd == wds[i]) { 159 snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name); 160 if (event->mask == IN_CREATE) { 161 D("new device %s\n", path); 162 if (s_added_cb) 163 s_added_cb(path); 164 } else if (event->mask == IN_DELETE) { 165 D("gone device %s\n", path); 166 if (s_removed_cb) 167 s_removed_cb(path); 168 } 169 } 170 } 171 } 172 } 173 } 174 return NULL; 175} 176 177int usb_host_init(usb_device_added_cb added_cb, usb_device_removed_cb removed_cb) 178{ 179 pthread_t tid; 180 181 s_added_cb = added_cb; 182 s_removed_cb = removed_cb; 183 184 if (added_cb || removed_cb) { 185 pthread_attr_t attr; 186 187 pthread_attr_init(&attr); 188 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 189 return pthread_create(&tid, &attr, device_discovery_thread, NULL); 190 } 191 else 192 return 0; 193} 194 195struct usb_device *usb_device_open(const char *dev_name) 196{ 197 struct usb_device *device = calloc(1, sizeof(struct usb_device)); 198 int fd, length, did_retry = 0; 199 200 strcpy(device->dev_name, dev_name); 201 device->writeable = 1; 202 203retry: 204 fd = open(dev_name, O_RDWR); 205 if (fd < 0) { 206 /* if we fail, see if have read-only access */ 207 fd = open(dev_name, O_RDONLY); 208 if (fd < 0 && errno == EACCES && !did_retry) { 209 /* work around race condition between inotify and permissions management */ 210 sleep(1); 211 did_retry = 1; 212 goto retry; 213 } 214 215 if (fd < 0) goto fail; 216 device->writeable = 0; 217 D("[ usb open read-only %s fd = %d]\n", dev_name, fd); 218 } 219 220 length = read(fd, device->desc, sizeof(device->desc)); 221 if (length < 0) 222 goto fail; 223 224 device->fd = fd; 225 device->desc_length = length; 226 return device; 227fail: 228 close(fd); 229 free(device); 230 return NULL; 231} 232 233void usb_device_close(struct usb_device *device) 234{ 235 close(device->fd); 236 free(device); 237} 238 239const char* usb_device_get_name(struct usb_device *device) 240{ 241 return device->dev_name; 242} 243 244uint16_t usb_device_get_vendor_id(struct usb_device *device) 245{ 246 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; 247 return __le16_to_cpu(desc->idVendor); 248} 249 250uint16_t usb_device_get_product_id(struct usb_device *device) 251{ 252 struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; 253 return __le16_to_cpu(desc->idProduct); 254} 255 256char* usb_device_get_string(struct usb_device *device, int id) 257{ 258 char string[256]; 259 struct usbdevfs_ctrltransfer ctrl; 260 __u16 buffer[128]; 261 __u16 languages[128]; 262 int i, result; 263 int languageCount = 0; 264 265 string[0] = 0; 266 267 // reading the string requires read/write permission 268 if (!device->writeable) { 269 int fd = open(device->dev_name, O_RDWR); 270 if (fd > 0) { 271 close(device->fd); 272 device->fd = fd; 273 device->writeable = 1; 274 } else { 275 return NULL; 276 } 277 } 278 279 memset(languages, 0, sizeof(languages)); 280 memset(&ctrl, 0, sizeof(ctrl)); 281 282 // read list of supported languages 283 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; 284 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 285 ctrl.wValue = (USB_DT_STRING << 8) | 0; 286 ctrl.wIndex = 0; 287 ctrl.wLength = sizeof(languages); 288 ctrl.data = languages; 289 290 result = ioctl(device->fd, USBDEVFS_CONTROL, &ctrl); 291 if (result > 0) 292 languageCount = (result - 2) / 2; 293 294 for (i = 1; i <= languageCount; i++) { 295 memset(buffer, 0, sizeof(buffer)); 296 memset(&ctrl, 0, sizeof(ctrl)); 297 298 ctrl.bRequestType = USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE; 299 ctrl.bRequest = USB_REQ_GET_DESCRIPTOR; 300 ctrl.wValue = (USB_DT_STRING << 8) | id; 301 ctrl.wIndex = languages[i]; 302 ctrl.wLength = sizeof(buffer); 303 ctrl.data = buffer; 304 305 result = ioctl(device->fd, USBDEVFS_CONTROL, &ctrl); 306 if (result > 0) { 307 int i; 308 // skip first word, and copy the rest to the string, changing shorts to bytes. 309 result /= 2; 310 for (i = 1; i < result; i++) 311 string[i - 1] = buffer[i]; 312 string[i - 1] = 0; 313 return strdup(string); 314 } 315 } 316 317 return NULL; 318} 319 320char* usb_device_get_manufacturer_name(struct usb_device *device) 321{ 322 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; 323 324 if (desc->iManufacturer) 325 return usb_device_get_string(device, desc->iManufacturer); 326 else 327 return NULL; 328} 329 330char* usb_device_get_product_name(struct usb_device *device) 331{ 332 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; 333 334 if (desc->iProduct) 335 return usb_device_get_string(device, desc->iProduct); 336 else 337 return NULL; 338} 339 340char* usb_device_get_serial(struct usb_device *device) 341{ 342 struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; 343 344 if (desc->iSerialNumber) 345 return usb_device_get_string(device, desc->iSerialNumber); 346 else 347 return NULL; 348} 349 350int usb_device_is_writeable(struct usb_device *device) 351{ 352 return device->writeable; 353} 354 355void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter) 356{ 357 iter->config = device->desc; 358 iter->config_end = device->desc + device->desc_length; 359 iter->curr_desc = device->desc; 360} 361 362struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter) 363{ 364 struct usb_descriptor_header* next; 365 if (iter->curr_desc >= iter->config_end) 366 return NULL; 367 next = (struct usb_descriptor_header*)iter->curr_desc; 368 iter->curr_desc += next->bLength; 369 return next; 370} 371 372int usb_device_claim_interface(struct usb_device *device, unsigned int interface) 373{ 374 return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface); 375} 376 377int usb_device_release_interface(struct usb_device *device, unsigned int interface) 378{ 379 return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface); 380} 381 382struct usb_endpoint *usb_endpoint_open(struct usb_device *dev, 383 const struct usb_endpoint_descriptor *desc) 384{ 385 struct usb_endpoint *ep = calloc(1, sizeof(struct usb_endpoint)); 386 memcpy(&ep->desc, desc, sizeof(ep->desc)); 387 ep->dev = dev; 388 return ep; 389} 390 391void usb_endpoint_close(struct usb_endpoint *ep) 392{ 393 // cancel IO here? 394 free(ep); 395} 396 397int usb_endpoint_queue(struct usb_endpoint *ep, void *data, int len) 398{ 399 struct usbdevfs_urb *urb = &ep->urb; 400 int res; 401 402 D("usb_endpoint_queue\n"); 403 memset(urb, 0, sizeof(*urb)); 404 urb->type = USBDEVFS_URB_TYPE_BULK; 405 urb->endpoint = ep->desc.bEndpointAddress; 406 urb->status = -1; 407 urb->buffer = data; 408 urb->buffer_length = len; 409 410 do { 411 res = ioctl(ep->dev->fd, USBDEVFS_SUBMITURB, urb); 412 } while((res < 0) && (errno == EINTR)); 413 414 return res; 415} 416 417int usb_endpoint_wait(struct usb_device *dev, int *out_ep_num) 418{ 419 struct usbdevfs_urb *out = NULL; 420 int res; 421 422 while (1) { 423 res = ioctl(dev->fd, USBDEVFS_REAPURB, &out); 424 D("USBDEVFS_REAPURB returned %d\n", res); 425 if (res < 0) { 426 if(errno == EINTR) { 427 continue; 428 } 429 D("[ reap urb - error ]\n"); 430 *out_ep_num = -1; 431 } else { 432 D("[ urb @%p status = %d, actual = %d ]\n", 433 out, out->status, out->actual_length); 434 res = out->actual_length; 435 *out_ep_num = out->endpoint; 436 } 437 break; 438 } 439 return res; 440} 441 442int usb_endpoint_cancel(struct usb_endpoint *ep) 443{ 444 return ioctl(ep->dev->fd, USBDEVFS_DISCARDURB, &ep->urb); 445} 446 447struct usb_device *usb_endpoint_get_device(struct usb_endpoint *ep) 448{ 449 return ep->dev; 450} 451 452int usb_endpoint_number(struct usb_endpoint *ep) 453{ 454 return ep->desc.bEndpointAddress; 455} 456 457int usb_endpoint_max_packet(struct usb_endpoint *ep) 458{ 459 return __le16_to_cpu(ep->desc.wMaxPacketSize); 460} 461 462