get_device fixup
[platform/upstream/libusb.git] / libusb / core.c
1 /*
2  * Core functions for libusb
3  * Copyright (C) 2007-2008 Daniel Drake <dsd@gentoo.org>
4  * Copyright (c) 2001 Johannes Erdfelt <johannes@erdfelt.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include <config.h>
22
23 #include <dirent.h>
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <features.h>
27 #include <poll.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36
37 #include "libusb.h"
38 #include "libusbi.h"
39
40 struct list_head usb_devs;
41 struct list_head open_devs;
42 static const char *usbfs_path = NULL;
43
44 static int check_usb_vfs(const char *dirname)
45 {
46         DIR *dir;
47         struct dirent *entry;
48         int found = 0;
49
50         dir = opendir(dirname);
51         if (!dir)
52                 return 0;
53
54         while ((entry = readdir(dir)) != NULL) {
55                 if (entry->d_name[0] == '.')
56                         continue;
57
58                 /* We assume if we find any files that it must be the right place */
59                 found = 1;
60                 break;
61         }
62
63         closedir(dir);
64         return found;
65 }
66
67 static const char *find_usbfs_path(void)
68 {
69         const char *path = "/dev/bus/usb";
70         const char *ret = NULL;
71
72         if (check_usb_vfs(path)) {
73                 ret = path;
74         } else {
75                 path = "/proc/bus/usb";
76                 if (check_usb_vfs(path))
77                         ret = path;
78         }
79
80         usbi_dbg("found usbfs at %s", ret);
81         return ret;
82 }
83
84 /* we traverse usbfs without knowing how many devices we are going to find.
85  * so we create this discovered_devs model which is similar to a linked-list
86  * which grows when required. it can be freed once discovery has completed,
87  * eliminating the need for a list node in the libusb_device structure
88  * itself. */
89 #define DISCOVERED_DEVICES_SIZE_STEP 8
90 struct discovered_devs {
91         size_t len;
92         size_t capacity;
93         struct libusb_device *devices[0];
94 };
95
96 static struct discovered_devs *discovered_devs_alloc(void)
97 {
98         struct discovered_devs *ret =
99                 malloc(sizeof(*ret) + (sizeof(void *) * DISCOVERED_DEVICES_SIZE_STEP));
100
101         if (ret) {
102                 ret->len = 0;
103                 ret->capacity = DISCOVERED_DEVICES_SIZE_STEP;
104         }
105         return ret;
106 }
107
108 /* append a device to the discovered devices collection. may realloc itself,
109  * returning new discdevs. returns NULL on realloc failure. */
110 static struct discovered_devs *discovered_devs_append(
111         struct discovered_devs *discdevs, struct libusb_device *dev)
112 {
113         size_t len = discdevs->len;
114         size_t capacity;
115
116         /* if there is space, just append the device */
117         if (len < discdevs->capacity) {
118                 discdevs->devices[len] = libusb_device_ref(dev);
119                 discdevs->len++;
120                 return discdevs;
121         }
122
123         /* exceeded capacity, need to grow */
124         usbi_dbg("need to increase capacity");
125         capacity = discdevs->capacity + DISCOVERED_DEVICES_SIZE_STEP;
126         discdevs = realloc(discdevs,
127                 sizeof(*discdevs) + (sizeof(void *) * capacity));
128         if (discdevs) {
129                 discdevs->capacity = capacity;
130                 discdevs->devices[len] = libusb_device_ref(dev);
131                 discdevs->len++;
132         }
133
134         return discdevs;
135 }
136
137 static void discovered_devs_free(struct discovered_devs *discdevs)
138 {
139         size_t i;
140
141         for (i = 0; i < discdevs->len; i++)
142                 libusb_device_unref(discdevs->devices[i]);
143
144         free(discdevs);
145 }
146
147 static struct libusb_device *device_new(uint8_t busnum, uint8_t devaddr)
148 {
149         char path[PATH_MAX + 1];
150         unsigned char raw_desc[DEVICE_DESC_LENGTH];
151         struct libusb_device *dev = malloc(sizeof(*dev));
152         int fd = 0;
153         int i;
154         int r;
155         int tmp;
156
157         if (!dev)
158                 return NULL;
159
160         dev->refcnt = 1;
161         dev->nodepath = NULL;
162         dev->config = NULL;
163
164         snprintf(path, PATH_MAX, "%s/%03d/%03d", usbfs_path, busnum, devaddr);
165         usbi_dbg("%s", path);
166         fd = open(path, O_RDWR);
167         if (!fd) {
168                 usbi_dbg("open '%s' failed, ret=%d errno=%d", path, fd, errno);
169                 /* FIXME this might not be an error if the file has gone away due
170                  * to unplugging */
171                 goto err;
172         }
173
174         r = read(fd, raw_desc, DEVICE_DESC_LENGTH);
175         if (r < 0) {
176                 usbi_err("read failed ret=%d errno=%d", r, errno);
177                 goto err;
178         }
179         /* FIXME: short read handling? */
180
181         usbi_parse_descriptor(raw_desc, "bbWbbbbWWWbbbb", &dev->desc);
182
183         /* Now try to fetch the rest of the descriptors */
184         if (dev->desc.bNumConfigurations > USB_MAXCONFIG) {
185                 usbi_err("too many configurations");
186                 goto err;
187         }
188
189         if (dev->desc.bNumConfigurations < 1) {
190                 usbi_dbg("no configurations?");
191                 goto err;
192         }
193
194         tmp = dev->desc.bNumConfigurations * sizeof(struct libusb_config_descriptor);
195         dev->config = malloc(tmp);
196         if (!dev->config)
197                 goto err;
198
199         memset(dev->config, 0, tmp);
200         for (i = 0; i < dev->desc.bNumConfigurations; i++) {
201                 unsigned char buffer[8], *bigbuffer;
202                 struct libusb_config_descriptor config;
203
204                 /* Get the first 8 bytes to figure out what the total length is */
205                 r = read(fd, buffer, sizeof(buffer));
206                 if (r < sizeof(buffer)) {
207                         usbi_err("short descriptor read (%d/%d)", r, sizeof(buffer));
208                         goto err;
209                 }
210
211                 usbi_parse_descriptor(buffer, "bbw", &config);
212
213                 bigbuffer = malloc(config.wTotalLength);
214                 if (!bigbuffer)
215                         goto err;
216
217                 /* Read the rest of the config descriptor */
218                 memcpy(bigbuffer, buffer, sizeof(buffer));
219
220                 tmp = config.wTotalLength - 8;
221                 r = read(fd, bigbuffer + 8, tmp);
222                 if (r < tmp) {
223                         usbi_err("short descriptor read (%d/%d)", r, tmp);
224                         free(bigbuffer);
225                         goto err;
226                 }
227
228                 r = usbi_parse_configuration(&dev->config[i], bigbuffer);
229                 if (r > 0)
230                         usbi_warn("descriptor data still left\n");
231                 free(bigbuffer);
232         }
233
234         dev->nodepath = strdup(path);
235         if (!dev->nodepath)
236                 goto err;
237
238         dev->session_data = busnum << 8 | devaddr;
239         list_add(&dev->list, &usb_devs);
240         close(fd);
241         return dev;
242
243 err:
244         if (fd)
245                 close(fd);
246         if (dev->config)
247                 free(dev->config);
248         if (dev->nodepath)
249                 free(dev->nodepath);
250         if (dev)
251                 free(dev);
252         return NULL;
253 }
254
255 static struct libusb_device *get_device_by_session_id(unsigned long session_id)
256 {
257         struct libusb_device *dev;
258
259         list_for_each_entry(dev, &usb_devs, list)
260                 if (dev->session_data == session_id)
261                         return dev;
262
263         return NULL;
264 }
265
266 /* open a device file, set up the libusb_device structure for it, and add it to
267  * discdevs. on failure (non-zero return) the pre-existing discdevs should
268  * be destroyed (and devices freed). on success, the new discdevs pointer
269  * should be used it may have been moved. */
270 static int scan_device(struct discovered_devs **_discdevs, uint8_t busnum,
271         uint8_t devaddr)
272 {
273         struct discovered_devs *discdevs;
274         unsigned long session_id;
275         struct libusb_device *dev;
276         int need_unref = 0;
277         int r = 0;
278
279         /* FIXME: session ID is not guaranteed unique as addresses can wrap and
280          * will be reused. instead we should add a simple sysfs attribute with
281          * a session ID. */
282         session_id = busnum << 8 | devaddr;
283         usbi_dbg("busnum %d devaddr %d session_id %ld", busnum, devaddr,
284                 session_id);
285
286         dev = get_device_by_session_id(session_id);
287         if (dev) {
288                 usbi_dbg("using existing device for %d/%d (session %ld)",
289                         busnum, devaddr, session_id);
290         } else {
291                 usbi_dbg("allocating new device for %d/%d (session %ld)",
292                         busnum, devaddr, session_id);
293                 dev = device_new(busnum, devaddr);
294                 if (!dev) {
295                         r = -EIO;
296                         goto out;
297                 }
298                 need_unref = 1;
299         }
300
301         discdevs = discovered_devs_append(*_discdevs, dev);
302         if (!discdevs)
303                 r = -ENOMEM;
304         else
305                 *_discdevs = discdevs;
306
307 out:
308         if (need_unref)
309                 libusb_device_unref(dev);
310         return r;
311 }
312
313 /* open a bus directory and adds all discovered devices to discdevs. on
314  * failure (non-zero return) the pre-existing discdevs should be destroyed
315  * (and devices freed). on success, the new discdevs pointer should be used
316  * as it may have been moved. */
317 static int scan_busdir(struct discovered_devs **_discdevs, uint8_t busnum)
318 {
319         DIR *dir;
320         char dirpath[PATH_MAX + 1];
321         struct dirent *entry;
322         struct discovered_devs *discdevs = *_discdevs;
323         int r = 0;
324
325         snprintf(dirpath, PATH_MAX, "%s/%03d", usbfs_path, busnum);
326         usbi_dbg("%s", dirpath);
327         dir = opendir(dirpath);
328         if (!dir) {
329                 usbi_err("opendir '%s' failed, errno=%d", dirpath, errno);
330                 /* FIXME: should handle valid race conditions like hub unplugged
331                  * during directory iteration - this is not an error */
332                 return -1;
333         }
334
335         while ((entry = readdir(dir))) {
336                 int devaddr;
337
338                 if (entry->d_name[0] == '.')
339                         continue;
340
341                 devaddr = atoi(entry->d_name);
342                 if (devaddr == 0) {
343                         usbi_dbg("unknown dir entry %s", entry->d_name);
344                         continue;
345                 }
346
347                 r = scan_device(&discdevs, busnum, (uint8_t) devaddr);
348                 if (r < 0)
349                         goto out;
350         }
351
352         *_discdevs = discdevs;
353 out:
354         closedir(dir);
355         return r;
356 }
357
358 API_EXPORTED int libusb_get_device_list(struct libusb_device ***list)
359 {
360         DIR *buses;
361         struct discovered_devs *discdevs = discovered_devs_alloc();
362         struct dirent *entry;
363         struct libusb_device **ret;
364         int r = 0;
365         size_t i;
366         size_t len;
367         usbi_dbg("");
368
369         if (!discdevs)
370                 return -ENOMEM;
371
372         buses = opendir(usbfs_path);
373         if (!buses) {
374                 usbi_err("opendir buses failed errno=%d", errno);
375                 return -1;
376         }
377
378         while ((entry = readdir(buses))) {
379                 struct discovered_devs *discdevs_new = discdevs;
380                 int busnum;
381
382                 if (entry->d_name[0] == '.')
383                         continue;
384
385                 busnum = atoi(entry->d_name);
386                 if (busnum == 0) {
387                         usbi_dbg("unknown dir entry %s", entry->d_name);
388                         continue;
389                 }
390
391                 r = scan_busdir(&discdevs_new, busnum);
392                 if (r < 0)
393                         goto out;
394                 discdevs = discdevs_new;
395         }
396
397         /* convert discovered_devs into a list */
398         len = discdevs->len;
399         ret = malloc(sizeof(void *) * (len + 1));
400         if (!ret) {
401                 r = -ENOMEM;
402                 goto out;
403         }
404
405         ret[len] = NULL;
406         for (i = 0; i < len; i++) {
407                 struct libusb_device *dev = discdevs->devices[i];
408                 ret[i] = libusb_device_ref(dev);
409         }
410         *list = ret;
411
412 out:
413         discovered_devs_free(discdevs);
414         closedir(buses);
415         return r;
416 }
417
418 API_EXPORTED void libusb_free_device_list(struct libusb_device **list,
419         int unref_devices)
420 {
421         if (!list)
422                 return;
423
424         if (unref_devices) {
425                 int i = 0;
426                 struct libusb_device *dev;
427
428                 while ((dev = list[i++]) != NULL)
429                         libusb_device_unref(dev);
430         }
431         free(list);
432 }
433
434 API_EXPORTED struct libusb_device *libusb_device_ref(struct libusb_device *dev)
435 {
436         dev->refcnt++;
437         return dev;
438 }
439
440 API_EXPORTED void libusb_device_unref(struct libusb_device *dev)
441 {
442         if (!dev)
443                 return;
444
445         if (--dev->refcnt == 0) {
446                 usbi_dbg("destroy device %04x:%04x", dev->desc.idVendor,
447                         dev->desc.idProduct);
448                 list_del(&dev->list);
449                 free(dev->config);
450                 free(dev->nodepath);
451                 free(dev);
452         }
453 }
454
455 API_EXPORTED struct libusb_device_descriptor *libusb_get_device_descriptor(
456         struct libusb_device *dev)
457 {
458         return &dev->desc;
459 }
460
461 API_EXPORTED struct libusb_config_descriptor *libusb_get_config_descriptor(
462         struct libusb_device *dev)
463 {
464         return dev->config;
465 }
466
467 API_EXPORTED struct libusb_device_handle *libusb_open(struct libusb_device *dev)
468 {
469         struct libusb_device_handle *devh;
470         int fd;
471         usbi_dbg("open %04x:%04x", dev->desc.idVendor, dev->desc.idProduct);
472
473         fd = open(dev->nodepath, O_RDWR);
474         if (!fd) {
475                 usbi_err("open failed, code %d errno %d", fd, errno);
476                 return NULL;
477         }
478
479         devh = malloc(sizeof(*devh));
480         if (!devh) {
481                 close(fd);
482                 return NULL;
483         }
484
485         devh->fd = fd;
486         devh->dev = libusb_device_ref(dev);
487         list_add(&devh->list, &open_devs);
488         usbi_add_pollfd(fd, POLLOUT);
489         return devh;
490 }
491
492 /* convenience function for finding a device with a particular vendor/product
493  * combination. has limitations and is hence not intended for use in "real
494  * applications": if multiple devices have the same VID+PID it'll only
495  * give you the first one, etc. */
496 API_EXPORTED struct libusb_device_handle *libusb_open_device_with_vid_pid(
497         uint16_t vendor_id, uint16_t product_id)
498 {
499         struct libusb_device **devs;
500         struct libusb_device *found = NULL;
501         struct libusb_device *dev;
502         struct libusb_device_handle *devh;
503         size_t i = 0;
504
505         if (libusb_get_device_list(&devs) < 0)
506                 return NULL;
507
508         while ((dev = devs[i++]) != NULL) {
509                 struct libusb_device_descriptor *desc =
510                         libusb_get_device_descriptor(dev);
511                 if (desc->idVendor == vendor_id && desc->idProduct == product_id) {
512                         found = dev;
513                         break;
514                 }
515         }
516
517         if (found)
518                 devh = libusb_open(found);
519
520         libusb_free_device_list(devs, 1);
521         return devh;
522 }
523
524 static void do_close(struct libusb_device_handle *devh)
525 {
526         usbi_remove_pollfd(devh->fd);
527         close(devh->fd);
528         libusb_device_unref(devh->dev);
529 }
530
531 API_EXPORTED void libusb_close(struct libusb_device_handle *dev_handle)
532 {
533         if (!dev_handle)
534                 return;
535         usbi_dbg("");
536
537         list_del(&dev_handle->list);
538         do_close(dev_handle);
539         free(dev_handle);
540 }
541
542 API_EXPORTED struct libusb_device *libusb_get_device(
543         struct libusb_device_handle *dev_handle)
544 {
545         return dev_handle->dev;
546 }
547
548 API_EXPORTED int libusb_claim_interface(struct libusb_device_handle *dev,
549         int iface)
550 {
551         int r;
552         usbi_dbg("interface %d", iface);
553         
554         r = ioctl(dev->fd, IOCTL_USB_CLAIMINTF, &iface);
555         if (r < 0)
556                 usbi_err("claim interface failed, error %d", r);
557         return r;
558 }
559
560 API_EXPORTED int libusb_release_interface(struct libusb_device_handle *dev,
561         int iface)
562 {
563         int r;
564         usbi_dbg("interface %d", iface);
565
566         r = ioctl(dev->fd, IOCTL_USB_RELEASEINTF, &iface);
567         if (r < 0)
568                 usbi_err("release interface failed, error %d", r);
569         return r;
570 }
571
572 API_EXPORTED int libusb_init(void)
573 {
574         usbi_dbg("");
575         usbfs_path = find_usbfs_path();
576         if (!usbfs_path) {
577                 usbi_err("could not find usbfs");
578                 return -ENODEV;
579         }
580
581         list_init(&usb_devs);
582         list_init(&open_devs);
583         usbi_io_init();
584         return 0;
585 }
586
587 API_EXPORTED void libusb_exit(void)
588 {
589         struct libusb_device_handle *devh;
590         usbi_dbg("");
591         if (!list_empty(&open_devs)) {
592                 usbi_dbg("naughty app left some devices open!\n");
593                 list_for_each_entry(devh, &open_devs, list)
594                         do_close(devh);
595         }
596 }
597
598 API_EXPORTED size_t libusb_get_pollfds(struct libusb_pollfd **pollfds)
599 {
600         struct libusb_device_handle *devh;
601         struct libusb_pollfd *ret;
602         size_t cnt = 0;
603         size_t i = 0;
604
605         /* count number of open devices */
606         list_for_each_entry(devh, &open_devs, list)
607                 cnt++;
608
609         /* create array */
610         ret = calloc(cnt, sizeof(struct libusb_pollfd));
611         if (!ret)
612                 return -ENOMEM;
613
614         /* add fds */
615         list_for_each_entry(devh, &open_devs, list) {
616                 ret[i++].fd = devh->fd;
617                 ret[i].events = POLLOUT;
618         }
619         
620         *pollfds = ret;
621         return cnt;
622 }
623
624 void usbi_log(enum usbi_log_level level, const char *function,
625         const char *format, ...)
626 {
627         va_list args;
628         FILE *stream = stdout;
629         const char *prefix;
630
631         switch (level) {
632         case LOG_LEVEL_INFO:
633                 prefix = "info";
634                 break;
635         case LOG_LEVEL_WARNING:
636                 stream = stderr;
637                 prefix = "warning";
638                 break;
639         case LOG_LEVEL_ERROR:
640                 stream = stderr;
641                 prefix = "error";
642                 break;
643         case LOG_LEVEL_DEBUG:
644                 stream = stderr;
645                 prefix = "debug";
646                 break;
647         default:
648                 stream = stderr;
649                 prefix = "unknown";
650                 break;
651         }
652
653         fprintf(stream, "libusb:%s [%s] ", prefix, function);
654
655         va_start (args, format);
656         vfprintf(stream, format, args);
657         va_end (args);
658
659         fprintf(stream, "\n");
660 }
661