Quiet warnings introduced with the USB iso support.
[qemu] / usb-linux.c
1 /*
2  * Linux host USB redirector
3  *
4  * Copyright (c) 2005 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "vl.h"
25
26 #if defined(__linux__)
27 #include <dirent.h>
28 #include <sys/ioctl.h>
29 #include <linux/usbdevice_fs.h>
30 #include <linux/version.h>
31 #include <signal.h>
32
33 /* We redefine it to avoid version problems */
34 struct usb_ctrltransfer {
35     uint8_t  bRequestType;
36     uint8_t  bRequest;
37     uint16_t wValue;
38     uint16_t wIndex;
39     uint16_t wLength;
40     uint32_t timeout;
41     void *data;
42 };
43
44 typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
45                         int vendor_id, int product_id,
46                         const char *product_name, int speed);
47 static int usb_host_find_device(int *pbus_num, int *paddr,
48                                 char *product_name, int product_name_size,
49                                 const char *devname);
50
51 //#define DEBUG
52 //#define DEBUG_ISOCH
53 //#define USE_ASYNCIO
54
55 #define USBDEVFS_PATH "/proc/bus/usb"
56 #define PRODUCT_NAME_SZ 32
57 #define SIG_ISOCOMPLETE (SIGRTMIN+7)
58 #define MAX_ENDPOINTS 16
59
60 struct sigaction sigact;
61
62 /* endpoint association data */
63 struct endp_data {
64     uint8_t type;
65 };
66
67 /* FIXME: move USBPacket to PendingURB */
68 typedef struct USBHostDevice {
69     USBDevice dev;
70     int fd;
71     USBPacket *packet;
72     struct endp_data endp_table[MAX_ENDPOINTS];
73     int configuration;
74     uint8_t descr[1024];
75     int descr_len;
76     int urbs_ready;
77 } USBHostDevice;
78
79 typedef struct PendingURB {
80     struct usbdevfs_urb *urb;
81     USBHostDevice *dev;
82     QEMUBH *bh;
83     int status;
84     struct PendingURB *next;
85 } PendingURB;
86
87 static PendingURB *pending_urbs = NULL;
88
89 static int add_pending_urb(struct usbdevfs_urb *urb)
90 {
91     PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
92     if (purb) {
93         purb->urb = urb;
94         purb->dev = NULL;
95         purb->bh = NULL;
96         purb->status = 0;
97         purb->next = pending_urbs;
98         pending_urbs = purb;
99         return 1;
100     }
101     return 0;
102 }
103
104 static int del_pending_urb(struct usbdevfs_urb *urb)
105 {
106     PendingURB *purb = pending_urbs;
107     PendingURB *prev = NULL;
108
109     while (purb && purb->urb != urb) {
110         prev = purb;
111         purb = purb->next;
112     }
113
114     if (purb && purb->urb == urb) {
115         if (prev) {
116             prev->next = purb->next;
117         } else {
118             pending_urbs = purb->next;
119         }
120         qemu_free(purb);
121         return 1;
122     }
123     return 0;
124 }
125
126 #ifdef USE_ASYNCIO
127 static PendingURB *get_pending_urb(struct usbdevfs_urb *urb)
128 {
129     PendingURB *purb = pending_urbs;
130
131     while (purb && purb->urb != urb) {
132         purb = purb->next;
133     }
134
135     if (purb && purb->urb == urb) {
136         return purb;
137     }
138     return NULL;
139 }
140 #endif
141
142 static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
143 {
144     int dev_descr_len, config_descr_len;
145     int interface, nb_interfaces, nb_configurations;
146     int ret, i;
147
148     if (configuration == 0) /* address state - ignore */
149         return 1;
150
151     i = 0;
152     dev_descr_len = dev->descr[0];
153     if (dev_descr_len > dev->descr_len)
154         goto fail;
155     nb_configurations = dev->descr[17];
156
157     i += dev_descr_len;
158     while (i < dev->descr_len) {
159 #ifdef DEBUG
160         printf("i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
161                dev->descr[i], dev->descr[i+1]);
162 #endif
163         if (dev->descr[i+1] != USB_DT_CONFIG) {
164             i += dev->descr[i];
165             continue;
166         }
167         config_descr_len = dev->descr[i];
168
169         if (configuration == dev->descr[i + 5])
170             break;
171
172         i += config_descr_len;
173     }
174
175     if (i >= dev->descr_len) {
176         printf("usb_host: error - device has no matching configuration\n");
177         goto fail;
178     }
179     nb_interfaces = dev->descr[i + 4];
180
181 #ifdef USBDEVFS_DISCONNECT
182     /* earlier Linux 2.4 do not support that */
183     {
184         struct usbdevfs_ioctl ctrl;
185         for (interface = 0; interface < nb_interfaces; interface++) {
186             ctrl.ioctl_code = USBDEVFS_DISCONNECT;
187             ctrl.ifno = interface;
188             ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
189             if (ret < 0 && errno != ENODATA) {
190                 perror("USBDEVFS_DISCONNECT");
191                 goto fail;
192             }
193         }
194     }
195 #endif
196
197     /* XXX: only grab if all interfaces are free */
198     for (interface = 0; interface < nb_interfaces; interface++) {
199         ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
200         if (ret < 0) {
201             if (errno == EBUSY) {
202                 fprintf(stderr,
203                         "usb_host: warning - device already grabbed\n");
204             } else {
205                 perror("USBDEVFS_CLAIMINTERFACE");
206             }
207         fail:
208             return 0;
209         }
210     }
211
212 #ifdef DEBUG
213     printf("usb_host: %d interfaces claimed for configuration %d\n",
214            nb_interfaces, configuration);
215 #endif
216
217     return 1;
218 }
219
220 static void usb_host_handle_reset(USBDevice *dev)
221 {
222 #if 0
223     USBHostDevice *s = (USBHostDevice *)dev;
224     /* USBDEVFS_RESET, but not the first time as it has already be
225        done by the host OS */
226     ioctl(s->fd, USBDEVFS_RESET);
227 #endif
228 }
229
230 static void usb_host_handle_destroy(USBDevice *dev)
231 {
232     USBHostDevice *s = (USBHostDevice *)dev;
233
234     if (s->fd >= 0)
235         close(s->fd);
236     qemu_free(s);
237 }
238
239 static int usb_linux_update_endp_table(USBHostDevice *s);
240
241 static int usb_host_handle_control(USBDevice *dev,
242                                    int request,
243                                    int value,
244                                    int index,
245                                    int length,
246                                    uint8_t *data)
247 {
248     USBHostDevice *s = (USBHostDevice *)dev;
249     struct usb_ctrltransfer ct;
250     struct usbdevfs_setinterface si;
251     int intf_update_required = 0;
252     int ret;
253
254     if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
255         /* specific SET_ADDRESS support */
256         dev->addr = value;
257         return 0;
258     } else if (request == ((USB_RECIP_INTERFACE << 8) |
259                            USB_REQ_SET_INTERFACE)) {
260         /* set alternate setting for the interface */
261         si.interface = index;
262         si.altsetting = value;
263         ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
264         usb_linux_update_endp_table(s);
265     } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
266 #ifdef DEBUG
267         printf("usb_host_handle_control: SET_CONFIGURATION request - "
268                "config %d\n", value & 0xff);
269 #endif
270         if (s->configuration != (value & 0xff)) {
271             s->configuration = (value & 0xff);
272             intf_update_required = 1;
273         }
274         goto do_request;
275     } else {
276     do_request:
277         ct.bRequestType = request >> 8;
278         ct.bRequest = request;
279         ct.wValue = value;
280         ct.wIndex = index;
281         ct.wLength = length;
282         ct.timeout = 50;
283         ct.data = data;
284         ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
285     }
286
287     if (ret < 0) {
288         switch(errno) {
289         case ETIMEDOUT:
290             return USB_RET_NAK;
291         default:
292             return USB_RET_STALL;
293         }
294     } else {
295         if (intf_update_required) {
296 #ifdef DEBUG
297             printf("usb_host_handle_control: updating interfaces\n");
298 #endif
299             usb_host_update_interfaces(s, value & 0xff);
300         }
301         return ret;
302     }
303 }
304
305 static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p);
306
307 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
308 {
309     USBHostDevice *s = (USBHostDevice *)dev;
310     struct usbdevfs_bulktransfer bt;
311     int ret;
312     uint8_t devep = p->devep;
313
314     if (s->endp_table[p->devep - 1].type == USBDEVFS_URB_TYPE_ISO) {
315         return usb_host_handle_isoch(dev, p);
316     }
317
318     /* XXX: optimize and handle all data types by looking at the
319        config descriptor */
320     if (p->pid == USB_TOKEN_IN)
321         devep |= 0x80;
322     bt.ep = devep;
323     bt.len = p->len;
324     bt.timeout = 50;
325     bt.data = p->data;
326     ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
327     if (ret < 0) {
328         switch(errno) {
329         case ETIMEDOUT:
330             return USB_RET_NAK;
331         case EPIPE:
332         default:
333 #ifdef DEBUG
334             printf("handle_data: errno=%d\n", errno);
335 #endif
336             return USB_RET_STALL;
337         }
338     } else {
339         return ret;
340     }
341 }
342
343 #ifdef USE_ASYNCIO
344 static void usb_linux_bh_cb(void *opaque)
345 {
346     PendingURB *pending_urb = (PendingURB *)opaque;
347     USBHostDevice *s = pending_urb->dev;
348     struct usbdevfs_urb *purb = NULL;
349     USBPacket *p = s->packet;
350     int ret;
351
352     /* FIXME: handle purb->status */
353     qemu_free(pending_urb->bh);
354     del_pending_urb(pending_urb->urb);
355
356     if (!p) {
357         s->urbs_ready++;
358         return;
359     }
360
361     ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
362     if (ret < 0) {
363         printf("usb_linux_bh_cb: REAPURBNDELAY ioctl=%d errno=%d\n",
364                ret, errno);
365         return;
366     }
367
368 #ifdef DEBUG_ISOCH
369     if (purb == pending_urb->urb) {
370         printf("usb_linux_bh_cb: urb mismatch reaped=%p pending=%p\n",
371                purb, urb);
372     }
373 #endif
374
375     p->len = purb->actual_length;
376     usb_packet_complete(p);
377     qemu_free(purb);
378     s->packet = NULL;
379 }
380
381 static void isoch_done(int signum, siginfo_t *info, void *context)
382 {
383     struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
384     USBHostDevice *s = (USBHostDevice *)urb->usercontext;
385     PendingURB *purb;
386
387     if (info->si_code != SI_ASYNCIO ||
388         info->si_signo != SIG_ISOCOMPLETE) {
389         return;
390     }
391
392     purb = get_pending_urb(urb);
393     if (purb) {
394         purb->bh = qemu_bh_new(usb_linux_bh_cb, purb);
395         if (purb->bh) {
396             purb->dev = s;
397             purb->status = info->si_errno;
398             qemu_bh_schedule(purb->bh);
399         }
400     }
401 }
402 #endif
403
404 static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p)
405 {
406     USBHostDevice *s = (USBHostDevice *)dev;
407     struct usbdevfs_urb *urb, *purb = NULL;
408     int ret;
409     uint8_t devep = p->devep;
410
411     if (p->pid == USB_TOKEN_IN)
412         devep |= 0x80;
413
414     urb = qemu_mallocz(sizeof(struct usbdevfs_urb) +
415                        sizeof(struct usbdevfs_iso_packet_desc));
416     if (!urb) {
417         printf("usb_host_handle_isoch: malloc failed\n");
418         return 0;
419     }
420
421     urb->type = USBDEVFS_URB_TYPE_ISO;
422     urb->endpoint = devep;
423     urb->status = 0;
424     urb->flags = USBDEVFS_URB_ISO_ASAP;
425     urb->buffer = p->data;
426     urb->buffer_length = p->len;
427     urb->actual_length = 0;
428     urb->start_frame = 0;
429     urb->error_count = 0;
430 #ifdef USE_ASYNCIO
431     urb->signr = SIG_ISOCOMPLETE;
432 #else
433     urb->signr = 0;
434 #endif
435     urb->usercontext = s;
436     urb->number_of_packets = 1;
437     urb->iso_frame_desc[0].length = p->len;
438     urb->iso_frame_desc[0].actual_length = 0;
439     urb->iso_frame_desc[0].status = 0;
440     ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
441     if (ret == 0) {
442         if (!add_pending_urb(urb)) {
443             printf("usb_host_handle_isoch: add_pending_urb failed %p\n", urb);
444         }
445     } else {
446         printf("usb_host_handle_isoch: SUBMITURB ioctl=%d errno=%d\n",
447                ret, errno);
448         qemu_free(urb);
449         switch(errno) {
450         case ETIMEDOUT:
451             return USB_RET_NAK;
452         case EPIPE:
453         default:
454             return USB_RET_STALL;
455         }
456     }
457 #ifdef USE_ASYNCIO
458     /* FIXME: handle urbs_ready together with sync io
459      * workaround for injecting the signaled urbs into current frame */
460     if (s->urbs_ready > 0) {
461         ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
462         if (ret == 0) {
463             ret = purb->actual_length;
464             qemu_free(purb);
465             s->urbs_ready--;
466         }
467         return ret;
468     }
469     s->packet = p;
470     return USB_RET_ASYNC;
471 #else
472     ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
473     if (ret == 0) {
474         if (del_pending_urb(purb)) {
475             ret = purb->actual_length;
476             qemu_free(purb);
477         } else {
478             printf("usb_host_handle_isoch: del_pending_urb failed %p\n", purb);
479         }
480     } else {
481 #ifdef DEBUG_ISOCH
482         printf("usb_host_handle_isoch: REAPURBNDELAY ioctl=%d errno=%d\n",
483                ret, errno);
484 #endif
485     }
486     return ret;
487 #endif
488 }
489
490 /* returns 1 on problem encountered or 0 for success */
491 static int usb_linux_update_endp_table(USBHostDevice *s)
492 {
493     uint8_t *descriptors;
494     uint8_t devep, type, configuration, alt_interface;
495     struct usb_ctrltransfer ct;
496     int interface, ret, length, i;
497
498     ct.bRequestType = USB_DIR_IN;
499     ct.bRequest = USB_REQ_GET_CONFIGURATION;
500     ct.wValue = 0;
501     ct.wIndex = 0;
502     ct.wLength = 1;
503     ct.data = &configuration;
504     ct.timeout = 50;
505
506     ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
507     if (ret < 0) {
508         perror("usb_linux_update_endp_table");
509         return 1;
510     }
511
512     /* in address state */
513     if (configuration == 0)
514         return 1;
515
516     /* get the desired configuration, interface, and endpoint descriptors
517      * from device description */
518     descriptors = &s->descr[18];
519     length = s->descr_len - 18;
520     i = 0;
521
522     if (descriptors[i + 1] != USB_DT_CONFIG ||
523         descriptors[i + 5] != configuration) {
524         printf("invalid descriptor data - configuration\n");
525         return 1;
526     }
527     i += descriptors[i];
528
529     while (i < length) {
530         if (descriptors[i + 1] != USB_DT_INTERFACE ||
531             (descriptors[i + 1] == USB_DT_INTERFACE &&
532              descriptors[i + 4] == 0)) {
533             i += descriptors[i];
534             continue;
535         }
536
537         interface = descriptors[i + 2];
538
539         ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
540         ct.bRequest = USB_REQ_GET_INTERFACE;
541         ct.wValue = 0;
542         ct.wIndex = interface;
543         ct.wLength = 1;
544         ct.data = &alt_interface;
545         ct.timeout = 50;
546
547         ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
548         if (ret < 0) {
549             perror("usb_linux_update_endp_table");
550             return 1;
551         }
552
553         /* the current interface descriptor is the active interface
554          * and has endpoints */
555         if (descriptors[i + 3] != alt_interface) {
556             i += descriptors[i];
557             continue;
558         }
559
560         /* advance to the endpoints */
561         while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
562             i += descriptors[i];
563
564         if (i >= length)
565             break;
566
567         while (i < length) {
568             if (descriptors[i + 1] != USB_DT_ENDPOINT)
569                 break;
570
571             devep = descriptors[i + 2];
572             switch (descriptors[i + 3] & 0x3) {
573             case 0x00:
574                 type = USBDEVFS_URB_TYPE_CONTROL;
575                 break;
576             case 0x01:
577                 type = USBDEVFS_URB_TYPE_ISO;
578                 break;
579             case 0x02:
580                 type = USBDEVFS_URB_TYPE_BULK;
581                 break;
582             case 0x03:
583                 type = USBDEVFS_URB_TYPE_INTERRUPT;
584                 break;
585             default:
586                 printf("usb_host: malformed endpoint type\n");
587                 type = USBDEVFS_URB_TYPE_BULK;
588             }
589             s->endp_table[(devep & 0xf) - 1].type = type;
590
591             i += descriptors[i];
592         }
593     }
594     return 0;
595 }
596
597 /* XXX: exclude high speed devices or implement EHCI */
598 USBDevice *usb_host_device_open(const char *devname)
599 {
600     int fd = -1, ret;
601     USBHostDevice *dev = NULL;
602     struct usbdevfs_connectinfo ci;
603     char buf[1024];
604     int bus_num, addr;
605     char product_name[PRODUCT_NAME_SZ];
606
607     dev = qemu_mallocz(sizeof(USBHostDevice));
608     if (!dev)
609         goto fail;
610
611 #ifdef DEBUG_ISOCH
612     printf("usb_host_device_open %s\n", devname);
613 #endif
614     if (usb_host_find_device(&bus_num, &addr,
615                              product_name, sizeof(product_name),
616                              devname) < 0)
617         return NULL;
618
619     snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
620              bus_num, addr);
621     fd = open(buf, O_RDWR | O_NONBLOCK);
622     if (fd < 0) {
623         perror(buf);
624         return NULL;
625     }
626
627     /* read the device description */
628     dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
629     if (dev->descr_len <= 0) {
630         perror("usb_host_update_interfaces: reading device data failed");
631         goto fail;
632     }
633
634 #ifdef DEBUG
635     {
636         int x;
637         printf("=== begin dumping device descriptor data ===\n");
638         for (x = 0; x < dev->descr_len; x++)
639             printf("%02x ", dev->descr[x]);
640         printf("\n=== end dumping device descriptor data ===\n");
641     }
642 #endif
643
644     dev->fd = fd;
645     dev->configuration = 1;
646
647     /* XXX - do something about initial configuration */
648     if (!usb_host_update_interfaces(dev, 1))
649         goto fail;
650
651     ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
652     if (ret < 0) {
653         perror("USBDEVFS_CONNECTINFO");
654         goto fail;
655     }
656
657 #ifdef DEBUG
658     printf("host USB device %d.%d grabbed\n", bus_num, addr);
659 #endif
660
661     ret = usb_linux_update_endp_table(dev);
662     if (ret)
663         goto fail;
664
665     if (ci.slow)
666         dev->dev.speed = USB_SPEED_LOW;
667     else
668         dev->dev.speed = USB_SPEED_HIGH;
669     dev->dev.handle_packet = usb_generic_handle_packet;
670
671     dev->dev.handle_reset = usb_host_handle_reset;
672     dev->dev.handle_control = usb_host_handle_control;
673     dev->dev.handle_data = usb_host_handle_data;
674     dev->dev.handle_destroy = usb_host_handle_destroy;
675
676     if (product_name[0] == '\0')
677         snprintf(dev->dev.devname, sizeof(dev->dev.devname),
678                  "host:%s", devname);
679     else
680         pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
681                 product_name);
682
683 #ifdef USE_ASYNCIO
684     /* set up the signal handlers */
685     sigemptyset(&sigact.sa_mask);
686     sigact.sa_sigaction = isoch_done;
687     sigact.sa_flags = SA_SIGINFO;
688     sigact.sa_restorer = 0;
689     ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
690     if (ret < 0) {
691         printf("sigaction SIG_ISOCOMPLETE=%d errno=%d\n", ret, errno);
692     }
693 #endif
694     dev->urbs_ready = 0;
695     return (USBDevice *)dev;
696 fail:
697     if (dev)
698         qemu_free(dev);
699     close(fd);
700     return NULL;
701 }
702
703 static int get_tag_value(char *buf, int buf_size,
704                          const char *str, const char *tag,
705                          const char *stopchars)
706 {
707     const char *p;
708     char *q;
709     p = strstr(str, tag);
710     if (!p)
711         return -1;
712     p += strlen(tag);
713     while (isspace(*p))
714         p++;
715     q = buf;
716     while (*p != '\0' && !strchr(stopchars, *p)) {
717         if ((q - buf) < (buf_size - 1))
718             *q++ = *p;
719         p++;
720     }
721     *q = '\0';
722     return q - buf;
723 }
724
725 static int usb_host_scan(void *opaque, USBScanFunc *func)
726 {
727     FILE *f;
728     char line[1024];
729     char buf[1024];
730     int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
731     int ret;
732     char product_name[512];
733
734     f = fopen(USBDEVFS_PATH "/devices", "r");
735     if (!f) {
736         term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
737         return 0;
738     }
739     device_count = 0;
740     bus_num = addr = speed = class_id = product_id = vendor_id = 0;
741     ret = 0;
742     for(;;) {
743         if (fgets(line, sizeof(line), f) == NULL)
744             break;
745         if (strlen(line) > 0)
746             line[strlen(line) - 1] = '\0';
747         if (line[0] == 'T' && line[1] == ':') {
748             if (device_count && (vendor_id || product_id)) {
749                 /* New device.  Add the previously discovered device.  */
750                 ret = func(opaque, bus_num, addr, class_id, vendor_id,
751                            product_id, product_name, speed);
752                 if (ret)
753                     goto the_end;
754             }
755             if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
756                 goto fail;
757             bus_num = atoi(buf);
758             if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
759                 goto fail;
760             addr = atoi(buf);
761             if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
762                 goto fail;
763             if (!strcmp(buf, "480"))
764                 speed = USB_SPEED_HIGH;
765             else if (!strcmp(buf, "1.5"))
766                 speed = USB_SPEED_LOW;
767             else
768                 speed = USB_SPEED_FULL;
769             product_name[0] = '\0';
770             class_id = 0xff;
771             device_count++;
772             product_id = 0;
773             vendor_id = 0;
774         } else if (line[0] == 'P' && line[1] == ':') {
775             if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
776                 goto fail;
777             vendor_id = strtoul(buf, NULL, 16);
778             if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
779                 goto fail;
780             product_id = strtoul(buf, NULL, 16);
781         } else if (line[0] == 'S' && line[1] == ':') {
782             if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
783                 goto fail;
784             pstrcpy(product_name, sizeof(product_name), buf);
785         } else if (line[0] == 'D' && line[1] == ':') {
786             if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
787                 goto fail;
788             class_id = strtoul(buf, NULL, 16);
789         }
790     fail: ;
791     }
792     if (device_count && (vendor_id || product_id)) {
793         /* Add the last device.  */
794         ret = func(opaque, bus_num, addr, class_id, vendor_id,
795                    product_id, product_name, speed);
796     }
797  the_end:
798     fclose(f);
799     return ret;
800 }
801
802 typedef struct FindDeviceState {
803     int vendor_id;
804     int product_id;
805     int bus_num;
806     int addr;
807     char product_name[PRODUCT_NAME_SZ];
808 } FindDeviceState;
809
810 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
811                                      int class_id,
812                                      int vendor_id, int product_id,
813                                      const char *product_name, int speed)
814 {
815     FindDeviceState *s = opaque;
816     if ((vendor_id == s->vendor_id &&
817         product_id == s->product_id) ||
818         (bus_num == s->bus_num &&
819         addr == s->addr)) {
820         pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name);
821         s->bus_num = bus_num;
822         s->addr = addr;
823         return 1;
824     } else {
825         return 0;
826     }
827 }
828
829 /* the syntax is :
830    'bus.addr' (decimal numbers) or
831    'vendor_id:product_id' (hexa numbers) */
832 static int usb_host_find_device(int *pbus_num, int *paddr,
833                                 char *product_name, int product_name_size,
834                                 const char *devname)
835 {
836     const char *p;
837     int ret;
838     FindDeviceState fs;
839
840     p = strchr(devname, '.');
841     if (p) {
842         *pbus_num = strtoul(devname, NULL, 0);
843         *paddr = strtoul(p + 1, NULL, 0);
844         fs.bus_num = *pbus_num;
845         fs.addr = *paddr;
846         ret = usb_host_scan(&fs, usb_host_find_device_scan);
847         if (ret)
848             pstrcpy(product_name, product_name_size, fs.product_name);
849         return 0;
850     }
851     p = strchr(devname, ':');
852     if (p) {
853         fs.vendor_id = strtoul(devname, NULL, 16);
854         fs.product_id = strtoul(p + 1, NULL, 16);
855         ret = usb_host_scan(&fs, usb_host_find_device_scan);
856         if (ret) {
857             *pbus_num = fs.bus_num;
858             *paddr = fs.addr;
859             pstrcpy(product_name, product_name_size, fs.product_name);
860             return 0;
861         }
862     }
863     return -1;
864 }
865
866 /**********************/
867 /* USB host device info */
868
869 struct usb_class_info {
870     int class;
871     const char *class_name;
872 };
873
874 static const struct usb_class_info usb_class_info[] = {
875     { USB_CLASS_AUDIO, "Audio"},
876     { USB_CLASS_COMM, "Communication"},
877     { USB_CLASS_HID, "HID"},
878     { USB_CLASS_HUB, "Hub" },
879     { USB_CLASS_PHYSICAL, "Physical" },
880     { USB_CLASS_PRINTER, "Printer" },
881     { USB_CLASS_MASS_STORAGE, "Storage" },
882     { USB_CLASS_CDC_DATA, "Data" },
883     { USB_CLASS_APP_SPEC, "Application Specific" },
884     { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
885     { USB_CLASS_STILL_IMAGE, "Still Image" },
886     { USB_CLASS_CSCID, "Smart Card" },
887     { USB_CLASS_CONTENT_SEC, "Content Security" },
888     { -1, NULL }
889 };
890
891 static const char *usb_class_str(uint8_t class)
892 {
893     const struct usb_class_info *p;
894     for(p = usb_class_info; p->class != -1; p++) {
895         if (p->class == class)
896             break;
897     }
898     return p->class_name;
899 }
900
901 void usb_info_device(int bus_num, int addr, int class_id,
902                      int vendor_id, int product_id,
903                      const char *product_name,
904                      int speed)
905 {
906     const char *class_str, *speed_str;
907
908     switch(speed) {
909     case USB_SPEED_LOW:
910         speed_str = "1.5";
911         break;
912     case USB_SPEED_FULL:
913         speed_str = "12";
914         break;
915     case USB_SPEED_HIGH:
916         speed_str = "480";
917         break;
918     default:
919         speed_str = "?";
920         break;
921     }
922
923     term_printf("  Device %d.%d, speed %s Mb/s\n",
924                 bus_num, addr, speed_str);
925     class_str = usb_class_str(class_id);
926     if (class_str)
927         term_printf("    %s:", class_str);
928     else
929         term_printf("    Class %02x:", class_id);
930     term_printf(" USB device %04x:%04x", vendor_id, product_id);
931     if (product_name[0] != '\0')
932         term_printf(", %s", product_name);
933     term_printf("\n");
934 }
935
936 static int usb_host_info_device(void *opaque, int bus_num, int addr,
937                                 int class_id,
938                                 int vendor_id, int product_id,
939                                 const char *product_name,
940                                 int speed)
941 {
942     usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
943                     product_name, speed);
944     return 0;
945 }
946
947 void usb_host_info(void)
948 {
949     usb_host_scan(NULL, usb_host_info_device);
950 }
951
952 #else
953
954 void usb_host_info(void)
955 {
956     term_printf("USB host devices not supported\n");
957 }
958
959 /* XXX: modify configure to compile the right host driver */
960 USBDevice *usb_host_device_open(const char *devname)
961 {
962     return NULL;
963 }
964
965 #endif