Change package group
[framework/system/usbutils.git] / lsusb-t.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <dirent.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <unistd.h>
10 #include <stddef.h>
11
12 #include "list.h"
13 #include "lsusb.h"
14
15 #define MY_SYSFS_FILENAME_LEN 255
16 #define MY_PATH_MAX 4096
17 #define MY_PARAM_MAX 64
18
19 struct usbinterface {
20         struct list_head list;
21         struct usbinterface *next;
22         struct usbdevice *parent;
23         unsigned int configuration;
24         unsigned int ifnum;
25
26         unsigned int bAlternateSetting;
27         unsigned int bInterfaceClass;
28         unsigned int bInterfaceNumber;
29         unsigned int bInterfaceProtocol;
30         unsigned int bInterfaceSubClass;
31         unsigned int bNumEndpoints;
32
33         char name[MY_SYSFS_FILENAME_LEN];
34         char driver[MY_SYSFS_FILENAME_LEN];
35 };
36
37 struct usbdevice {
38         struct list_head list;  /* connect devices independant of the bus */
39         struct usbdevice *next; /* next port on this hub */
40         struct usbinterface *first_interface;   /* list of interfaces */
41         struct usbdevice *first_child;  /* connect devices on this port */
42         struct usbdevice *parent;       /* hub this device is connected to */
43         unsigned int busnum;
44         unsigned int parent_portnum;
45         unsigned int portnum;
46
47         unsigned int bConfigurationValue;
48         unsigned int bDeviceClass;
49         unsigned int bDeviceProtocol;
50         unsigned int bDeviceSubClass;
51         unsigned int bMaxPacketSize0;
52         char bMaxPower[MY_PARAM_MAX];
53         unsigned int bNumConfigurations;
54         unsigned int bNumInterfaces;
55         unsigned int bcdDevice;
56         unsigned int bmAttributes;
57         unsigned int configuration;
58         unsigned int devnum;
59         unsigned int idProduct;
60         unsigned int idVendor;
61         unsigned int maxchild;
62         char manufacturer[MY_PARAM_MAX];
63         char product[MY_PARAM_MAX];
64         char serial[MY_PARAM_MAX];
65         char version[MY_PARAM_MAX];
66         char speed[MY_PARAM_MAX];       /* '1.5','12','480','5000' + '\n' */
67
68         char name[MY_SYSFS_FILENAME_LEN];
69         char driver[MY_SYSFS_FILENAME_LEN];
70 };
71
72 struct usbbusnode {
73         struct usbbusnode *next;
74         struct usbinterface *first_interface;   /* list of interfaces */
75         struct usbdevice *first_child;  /* connect childs belonging to this bus */
76         unsigned int busnum;
77
78         unsigned int bDeviceClass;
79         unsigned int devnum;
80         unsigned int maxchild;
81         char speed[5 + 1];      /* '1.5','12','480','5000' + '\n' */
82
83         char driver[MY_SYSFS_FILENAME_LEN];
84 };
85
86 #define SYSFS_INTu(de,tgt, name) do { tgt->name = read_sysfs_file_int(de,#name,10); } while(0)
87 #define SYSFS_INTx(de,tgt, name) do { tgt->name = read_sysfs_file_int(de,#name,16); } while(0)
88 #define SYSFS_STR(de,tgt, name) do { read_sysfs_file_string(de, #name, tgt->name, MY_PARAM_MAX); } while(0)
89
90 LIST_HEAD(interfacelist);
91 LIST_HEAD(usbdevlist);
92 static struct usbbusnode *usbbuslist;
93
94 static const char sys_bus_usb_devices[] = "/sys/bus/usb/devices";
95 static int indent;
96
97 #if 0
98 static void dump_usbbusnode(struct usbbusnode *b)
99 {
100         printf(" B %p:'%u': n %p fi %p fc %p driver '%s'\n", b, b->busnum, b->next, b->first_interface, b->first_child, b->driver);
101 }
102
103 static void dump_usbdevice(struct usbdevice *d)
104 {
105         printf
106             (" D %p:'%s': n %p fi %p fc %p bn %u ppn %u pn %u p %p bCV %u bDC %02x bDP %02x bDSC %02x bMPS %02x bMP '%s' bNC %u bNI %u bcdD %02x bmA %02x c %u dn %u idP %04x idV %04x mc %u m '%s' p '%s' s '%s' v '%s' sp '%s' driver '%s'\n",
107              d, d->name, d->next, d->first_interface, d->first_child, d->busnum, d->parent_portnum, d->portnum, d->parent, d->bConfigurationValue, d->bDeviceClass,
108              d->bDeviceProtocol, d->bDeviceSubClass, d->bMaxPacketSize0, d->bMaxPower, d->bNumConfigurations, d->bNumInterfaces, d->bcdDevice, d->bmAttributes,
109              d->configuration, d->devnum, d->idProduct, d->idVendor, d->maxchild, d->manufacturer, d->product, d->serial, d->version, d->speed, d->driver);
110 }
111
112 static void dump_usbinterface(struct usbinterface *i)
113 {
114         printf(" I %p:'%s': n %p c %u if %u bAS %u bIC %02x bIN %02x bIP %02x bISC %02x bNE %u d '%s'\n", i, i->name, i->next, i->configuration, i->ifnum,
115                i->bAlternateSetting, i->bInterfaceClass, i->bInterfaceNumber, i->bInterfaceProtocol, i->bInterfaceSubClass, i->bNumEndpoints, i->driver);
116 }
117 #endif
118
119 static char tmp_str[128];
120 static const char *bInterfaceClass_to_str(unsigned int dc)
121 {
122         const char *s;
123         switch (dc) {
124         case 0:
125                 s = ">ifc";
126                 break;
127         case 1:
128                 s = "audio";
129                 break;
130         case 2:
131                 s = "comm.";
132                 break;
133         case 3:
134                 s = "HID";
135                 break;
136         case 5:
137                 s = "PID";
138                 break;
139         case 6:
140                 s = "still";
141                 break;
142         case 7:
143                 s = "print";
144                 break;
145         case 8:
146                 s = "stor.";
147                 break;
148         case 9:
149                 s = "hub";
150                 break;
151         case 10:
152                 s = "data";
153                 break;
154         case 11:
155                 s = "scard";
156                 break;
157         case 13:
158                 s = "c-sec";
159                 break;
160         case 254:
161                 s = "app.";
162                 break;
163         case 255:
164                 s = "vend.";
165                 break;
166         default:
167                 snprintf(tmp_str, 128, "'bInterfaceClass 0x%02x not yet handled'", dc);;
168                 s = tmp_str;
169         }
170         return s;
171 }
172 static const char *bDeviceClass_to_str(unsigned int dc)
173 {
174         const char *s;
175         switch (dc) {
176         case 9:
177                 s = "root_hub";
178                 break;
179         default:
180                 snprintf(tmp_str, 128, "'bDeviceClass 0x%02x not yet handled'", dc);;
181                 s = tmp_str;
182         }
183         return s;
184 }
185 static void print_usbbusnode(struct usbbusnode *b)
186 {
187         printf("/:  Bus %02u.Port %u: Dev %u, Class=%s, Driver=%s/%up, %sM\n", b->busnum, 1,
188                b->devnum, bDeviceClass_to_str(b->bDeviceClass), b->driver, b->maxchild, b->speed);
189 }
190
191 static void print_usbdevice(struct usbdevice *d, struct usbinterface *i)
192 {
193         if (i->bInterfaceClass == 9)
194                 printf("Port %u: Dev %u, If %u, Class=%s, Driver=%s/%up, %sM\n", d->portnum, d->devnum, i->ifnum, bInterfaceClass_to_str(i->bInterfaceClass),
195                        i->driver, d->maxchild, d->speed);
196         else
197                 printf("Port %u: Dev %u, If %u, Class=%s, Driver=%s, %sM\n", d->portnum, d->devnum, i->ifnum, bInterfaceClass_to_str(i->bInterfaceClass), i->driver,
198                        d->speed);
199 }
200
201 static unsigned int read_sysfs_file_int(const char *d_name, const char *file, int base)
202 {
203         char buf[12], path[MY_PATH_MAX];
204         int fd;
205         ssize_t r;
206         unsigned long ret;
207         snprintf(path, MY_PATH_MAX, "%s/%s/%s", sys_bus_usb_devices, d_name, file);
208         path[MY_PATH_MAX - 1] = '\0';
209         fd = open(path, O_RDONLY);
210         if (fd < 0)
211                 goto error;
212         memset(buf, 0, sizeof(buf));
213         r = read(fd, buf, sizeof(buf) - 1);
214         close(fd);
215         if (r < 0)
216                 goto error;
217         buf[sizeof(buf) - 1] = '\0';
218         ret = strtoul(buf, NULL, base);
219         return (unsigned int)ret;
220
221       error:
222         perror(path);
223         return 0;
224 }
225
226 static void read_sysfs_file_string(const char *d_name, const char *file, char *buf, int len)
227 {
228         char path[MY_PATH_MAX];
229         int fd;
230         ssize_t r;
231         fd = snprintf(path, MY_PATH_MAX, "%s/%s/%s", sys_bus_usb_devices, d_name, file);
232         if (fd < 0 || fd >= MY_PATH_MAX)
233                 goto error;
234         path[fd] = '\0';
235         fd = open(path, O_RDONLY);
236         if (fd < 0)
237                 goto error;
238         r = read(fd, buf, len);
239         close(fd);
240         if (r > 0 && r < len) {
241                 buf[r] = '\0';
242                 r--;
243                 while (buf[r] == '\n') {
244                         buf[r] = '\0';
245                         r--;
246                 }
247                 while (r) {
248                         if (buf[r] == '\n')
249                                 buf[r] = ' ';
250                         r--;
251                 }
252                 return;
253         }
254       error:
255         buf[0] = '\0';
256 }
257
258 static void append_dev_interface(struct usbinterface *i, struct usbinterface *new)
259 {
260         while (i->next)
261                 i = i->next;
262         i->next = new;
263 }
264
265 static void append_dev_sibling(struct usbdevice *d, struct usbdevice *new)
266 {
267         while (d->next)
268                 d = d->next;
269         d->next = new;
270 }
271
272 static void append_businterface(unsigned int busnum, struct usbinterface *new)
273 {
274         struct usbbusnode *b = usbbuslist;
275         struct usbinterface *i;
276         while (b) {
277                 if (b->busnum == busnum) {
278                         i = b->first_interface;
279                         if (i) {
280                                 while (i->next)
281                                         i = i->next;
282                                 i->next = new;
283                         } else
284                                 b->first_interface = new;
285                         break;
286                 }
287                 b = b->next;
288         }
289 }
290
291 static void append_busnode(struct usbbusnode *new)
292 {
293         struct usbbusnode *b = usbbuslist;
294         if (b) {
295                 while (b->next)
296                         b = b->next;
297                 b->next = new;
298         } else
299                 usbbuslist = new;
300 }
301
302 static void add_usb_interface(const char *d_name)
303 {
304         struct usbinterface *e;
305         const char *p;
306         char *pn, driver[MY_PATH_MAX];
307         unsigned long i;
308         int l;
309         p = strchr(d_name, ':');
310         p++;
311         i = strtoul(p, &pn, 10);
312         if (!pn || p == pn)
313                 return;
314         e = malloc(sizeof(struct usbinterface));
315         if (!e)
316                 return;
317         memset(e, 0, sizeof(struct usbinterface));
318         e->configuration = i;
319         p = pn + 1;
320         i = strtoul(p, &pn, 10);
321         if (!pn || p == pn)
322         {
323                 free(e);
324                 return;
325         }
326         e->ifnum = i;
327         if (snprintf(e->name, MY_SYSFS_FILENAME_LEN, "%s", d_name) >= MY_SYSFS_FILENAME_LEN)
328                 printf("warning: '%s' truncated to '%s'\n", e->name, d_name);
329         SYSFS_INTu(d_name, e, bAlternateSetting);
330         SYSFS_INTx(d_name, e, bInterfaceClass);
331         SYSFS_INTx(d_name, e, bInterfaceNumber);
332         SYSFS_INTx(d_name, e, bInterfaceProtocol);
333         SYSFS_INTx(d_name, e, bInterfaceSubClass);
334         SYSFS_INTx(d_name, e, bNumEndpoints);
335         l = snprintf(driver, MY_PATH_MAX, "%s/%s/driver", sys_bus_usb_devices, d_name);
336         if (l > 0 && l < MY_PATH_MAX) {
337                 l = readlink(driver, driver, MY_PATH_MAX);
338                 if (l < 0)
339                         perror(d_name);
340                 else {
341                         if (l < MY_PATH_MAX - 1)
342                                 driver[l] = '\0';
343                         else
344                                 driver[0] = '\0';
345                         p = strrchr(driver, '/');
346                         if (p)
347                                 snprintf(e->driver, sizeof(e->driver), "%s", p + 1);
348                 }
349         } else
350                 printf("Can not read driver link for '%s': %d\n", d_name, l);
351         list_add_tail(&e->list, &interfacelist);
352 }
353
354 static void add_usb_device(const char *d_name)
355 {
356         struct usbdevice *d;
357         const char *p;
358         char *pn, driver[MY_PATH_MAX];
359         unsigned long i;
360         int l;
361         p = d_name;
362         i = strtoul(p, &pn, 10);
363         if (!pn || p == pn)
364                 return;
365         d = malloc(sizeof(struct usbdevice));
366         if (!d)
367                 return;
368         memset(d, 0, sizeof(struct usbdevice));
369         d->busnum = i;
370         while (pn) {
371                 p = pn + 1;
372                 i = strtoul(p, &pn, 10);
373                 if (p == pn)
374                         break;
375                 d->parent_portnum = d->portnum;
376                 d->portnum = i;
377         }
378         if (snprintf(d->name, MY_SYSFS_FILENAME_LEN, "%s", d_name) >= MY_SYSFS_FILENAME_LEN)
379                 printf("warning: '%s' truncated to '%s'\n", d->name, d_name);
380         SYSFS_INTu(d_name, d, bConfigurationValue);
381         SYSFS_INTx(d_name, d, bDeviceClass);
382         SYSFS_INTx(d_name, d, bDeviceProtocol);
383         SYSFS_INTx(d_name, d, bDeviceSubClass);
384         SYSFS_INTx(d_name, d, bMaxPacketSize0);
385         SYSFS_STR(d_name, d, bMaxPower);
386         SYSFS_INTu(d_name, d, bNumConfigurations);
387         SYSFS_INTx(d_name, d, bNumInterfaces);
388         SYSFS_INTx(d_name, d, bcdDevice);
389         SYSFS_INTx(d_name, d, bmAttributes);
390         SYSFS_INTu(d_name, d, configuration);
391         SYSFS_INTu(d_name, d, devnum);
392         SYSFS_INTx(d_name, d, idProduct);
393         SYSFS_INTx(d_name, d, idVendor);
394         SYSFS_INTu(d_name, d, maxchild);
395         SYSFS_STR(d_name, d, manufacturer);
396         SYSFS_STR(d_name, d, product);
397         SYSFS_STR(d_name, d, serial);
398         SYSFS_STR(d_name, d, version);
399         SYSFS_STR(d_name, d, speed);
400         l = snprintf(driver, MY_PATH_MAX, "%s/%s/driver", sys_bus_usb_devices, d_name);
401         if (l > 0 && l < MY_PATH_MAX) {
402                 l = readlink(driver, driver, MY_PATH_MAX);
403                 if (l < 0)
404                         perror(d_name);
405                 else {
406                         if (l < MY_PATH_MAX - 1)
407                                 driver[l] = '\0';
408                         else
409                                 driver[0] = '\0';
410                         p = strrchr(driver, '/');
411                         if (p)
412                                 snprintf(d->driver, sizeof(d->driver), "%s", p + 1);
413                 }
414         } else
415                 printf("Can not read driver link for '%s': %d\n", d_name, l);
416         list_add_tail(&d->list, &usbdevlist);
417 }
418
419 static void get_roothub_driver(struct usbbusnode *b, const char *d_name)
420 {
421         char *p, path[MY_PATH_MAX];
422         int l;
423         l = snprintf(path, MY_PATH_MAX, "%s/%s/../driver", sys_bus_usb_devices, d_name);
424         if (l > 0 && l < MY_PATH_MAX) {
425                 l = readlink(path, path, MY_PATH_MAX);
426                 if (l < 0)
427                         perror(d_name);
428                 else {
429                         if (l < MY_PATH_MAX - 1)
430                                 path[l] = '\0';
431                         else
432                                 path[0] = '\0';
433                         p = strrchr(path, '/');
434                         if (p)
435                                 snprintf(b->driver, sizeof(b->driver), "%s", p + 1);
436                 }
437         } else
438                 printf("Can not read driver link for '%s': %d\n", d_name, l);
439 }
440
441 static void add_usb_bus(const char *d_name)
442 {
443         struct usbbusnode *bus;
444         bus = malloc(sizeof(struct usbbusnode));
445         if (bus) {
446                 memset(bus, 0, sizeof(struct usbbusnode));
447                 bus->busnum = strtoul(d_name + 3, NULL, 10);
448                 SYSFS_INTu(d_name, bus, devnum);
449                 SYSFS_INTx(d_name, bus, bDeviceClass);
450                 SYSFS_INTu(d_name, bus, maxchild);
451                 SYSFS_STR(d_name, bus, speed);
452                 append_busnode(bus);
453                 get_roothub_driver(bus, d_name);
454         }
455 }
456
457 static void inspect_bus_entry(const char *d_name)
458 {
459         if (d_name[0] == '.' && (!d_name[1] || (d_name[1] == '.' && !d_name[2])))
460                 return;
461         if (d_name[0] == 'u' && d_name[1] == 's' && d_name[2] == 'b' && isdigit(d_name[3])) {
462                 add_usb_bus(d_name);
463         } else if (isdigit(d_name[0])) {
464                 if (strchr(d_name, ':'))
465                         add_usb_interface(d_name);
466                 else
467                         add_usb_device(d_name);
468         } else
469                 fprintf(stderr, "ignoring '%s'\n", d_name);
470 }
471
472 static void walk_usb_devices(DIR * sbud)
473 {
474         struct dirent *de;
475         while ((de = readdir(sbud)))
476                 inspect_bus_entry(de->d_name);
477 }
478
479 static void assign_dev_to_bus(struct usbdevice *d)
480 {
481         struct usbbusnode *b = usbbuslist;
482         while (b) {
483                 if (b->busnum == d->busnum) {
484                         if (b->first_child)
485                                 append_dev_sibling(b->first_child, d);
486                         else
487                                 b->first_child = d;
488                 }
489                 b = b->next;
490         }
491 }
492
493 static void assign_dev_to_parent(struct usbdevice *d)
494 {
495         struct list_head *l;
496         struct usbdevice *pd;
497         char n[MY_SYSFS_FILENAME_LEN], *p;
498         for (l = usbdevlist.next; l != &usbdevlist; l = l->next) {
499                 pd = list_entry(l, struct usbdevice, list);
500                 if (pd == d)
501                         continue;
502                 if (pd->busnum == d->busnum && pd->portnum == d->parent_portnum) {
503                         strcpy(n, d->name);
504                         p = strrchr(n, '.');
505                         if (p) {
506                                 *p = '\0';
507                                 if (strcmp(n, pd->name)) {
508                                         continue;
509                                 }
510                                 d->parent = pd;
511                                 if (pd->first_child)
512                                         append_dev_sibling(pd->first_child, d);
513                                 else
514                                         pd->first_child = d;
515                                 break;
516                         }
517                 }
518         }
519 }
520
521 static void assign_interface_to_parent(struct usbdevice *d, struct usbinterface *i)
522 {
523         const char *p;
524         char *pn, name[MY_SYSFS_FILENAME_LEN];
525         ptrdiff_t l;
526         unsigned int busnum;
527
528         p = strchr(i->name, ':');
529         if (p) {
530                 l = p - i->name;
531                 if (l < MY_SYSFS_FILENAME_LEN) {
532                         memcpy(name, i->name, l);
533                         name[l] = '\0';
534                 } else
535                         name[0] = '\0';
536                 if (strcmp(d->name, name) == 0) {
537                         i->parent = d;
538                         if (d->first_interface)
539                                 append_dev_interface(d->first_interface, i);
540                         else
541                                 d->first_interface = i;
542                 } else {
543                         busnum = strtoul(name, &pn, 10);
544                         if (pn && pn != name) {
545                                 if (p[1] == '0')
546                                         append_businterface(busnum, i);
547                         }
548                 }
549         }
550 }
551
552 static void connect_devices(void)
553 {
554         struct list_head *ld, *li;
555         struct usbdevice *d;
556         struct usbinterface *e;
557         for (ld = usbdevlist.next; ld != &usbdevlist; ld = ld->next) {
558                 d = list_entry(ld, struct usbdevice, list);
559                 if (d->parent_portnum)
560                         assign_dev_to_parent(d);
561                 else
562                         assign_dev_to_bus(d);
563                 for (li = interfacelist.next; li != &interfacelist; li = li->next) {
564                         e = list_entry(li, struct usbinterface, list);
565                         if (!e->parent)
566                                 assign_interface_to_parent(d, e);
567                 }
568         }
569         for (li = interfacelist.next; li != &interfacelist; li = li->next) {
570                 e = list_entry(li, struct usbinterface, list);
571         }
572 }
573
574 static void sort_dev_interfaces(struct usbinterface **i)
575 {
576         struct usbinterface *t, *p, **pp;
577         int swapped;
578         p = *i;
579         pp = i;
580         do {
581                 p = *i;
582                 pp = i;
583                 swapped = 0;
584                 while (p->next) {
585                         if (p->configuration > p->next->configuration) {
586                                 t = p->next;
587                                 p->next = t->next;
588                                 t->next = p;
589                                 *pp = t;
590                                 swapped = 1;
591                                 p = t;
592                         }
593                         if (p->ifnum > p->next->ifnum) {
594                                 t = p->next;
595                                 p->next = t->next;
596                                 t->next = p;
597                                 *pp = t;
598                                 swapped = 1;
599                                 p = t;
600                         }
601                         pp = &p->next;
602                         p = p->next;
603                 }
604         } while (swapped);
605 }
606
607 static void sort_dev_siblings(struct usbdevice **d)
608 {
609         struct usbdevice *t, *p, **pp;
610         int swapped;
611         p = *d;
612         pp = d;
613         if (p->first_child)
614                 sort_dev_siblings(&p->first_child);
615         if (p->first_interface)
616                 sort_dev_interfaces(&p->first_interface);
617         do {
618                 p = *d;
619                 pp = d;
620                 swapped = 0;
621                 while (p->next) {
622                         if (p->portnum > p->next->portnum) {
623                                 t = p->next;
624                                 p->next = t->next;
625                                 t->next = p;
626                                 *pp = t;
627                                 swapped = 1;
628                                 p = t;
629                         }
630                         pp = &p->next;
631                         p = p->next;
632                 }
633         } while (swapped);
634 }
635
636 static void sort_devices(void)
637 {
638         struct usbbusnode *b = usbbuslist;
639         while (b) {
640                 if (b->first_child)
641                         sort_dev_siblings(&b->first_child);
642                 b = b->next;
643         }
644 }
645
646 static void sort_busses(void)
647 {
648         /* need to reverse sort bus numbers */
649         struct usbbusnode *t, *p, **pp;
650         int swapped;
651         do {
652                 p = usbbuslist;
653                 pp = &usbbuslist;
654                 swapped = 0;
655                 while (p->next) {
656                         if (p->busnum < p->next->busnum) {
657                                 t = p->next;
658                                 p->next = t->next;
659                                 t->next = p;
660                                 *pp = t;
661                                 swapped = 1;
662                                 p = t;
663                         }
664                         pp = &p->next;
665                         p = p->next;
666                 }
667         } while (swapped);
668 }
669
670 static void print_tree_dev_interface(struct usbdevice *d, struct usbinterface *i)
671 {
672         indent += 3;
673         while (i) {
674                 printf(" %*s", indent, "|__ ");
675                 print_usbdevice(d, i);
676                 i = i->next;
677         }
678         indent -= 3;
679 }
680 static void print_tree_dev_children(struct usbdevice *d)
681 {
682         indent += 4;
683         while (d) {
684                 print_tree_dev_interface(d, d->first_interface);
685                 print_tree_dev_children(d->first_child);
686                 d = d->next;
687         }
688         indent -= 4;
689 }
690
691 static void print_tree(void)
692 {
693         struct usbbusnode *b = usbbuslist;
694         while (b) {
695                 print_usbbusnode(b);
696                 if (b->first_child)
697                         print_tree_dev_children(b->first_child);
698                 b = b->next;
699         }
700 }
701
702 int lsusb_t(void)
703 {
704         DIR *sbud = opendir(sys_bus_usb_devices);
705         if (sbud) {
706                 walk_usb_devices(sbud);
707                 closedir(sbud);
708                 connect_devices();
709                 sort_devices();
710                 sort_busses();
711                 print_tree();
712         } else
713                 perror(sys_bus_usb_devices);
714         return sbud == NULL;
715 }