2 * Linux host USB redirector
4 * Copyright (c) 2005 Fabrice Bellard
6 * Support for host device auto connect & disconnect
7 * Copyright (c) 2008 Max Krasnyansky
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 #include "qemu-common.h"
28 #include "qemu-timer.h"
32 #if defined(__linux__)
34 #include <sys/ioctl.h>
35 #include <linux/usbdevice_fs.h>
36 #include <linux/version.h>
39 /* We redefine it to avoid version problems */
40 struct usb_ctrltransfer {
50 typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id,
51 int vendor_id, int product_id,
52 const char *product_name, int speed);
53 static int usb_host_find_device(int *pbus_num, int *paddr,
54 char *product_name, int product_name_size,
61 #define USBDEVFS_PATH "/proc/bus/usb"
62 #define PRODUCT_NAME_SZ 32
63 #define SIG_ISOCOMPLETE (SIGRTMIN+7)
64 #define MAX_ENDPOINTS 16
66 struct sigaction sigact;
68 /* endpoint association data */
75 /* FIXME: move USBPacket to PendingURB */
76 typedef struct USBHostDevice {
81 struct endp_data endp_table[MAX_ENDPOINTS];
89 /* Host side address */
93 struct USBHostDevice *next;
96 static USBHostDevice *hostdev_list;
98 static void hostdev_link(USBHostDevice *dev)
100 dev->next = hostdev_list;
104 static void hostdev_unlink(USBHostDevice *dev)
106 USBHostDevice *pdev = hostdev_list;
107 USBHostDevice **prev = &hostdev_list;
120 static USBHostDevice *hostdev_find(int bus_num, int addr)
122 USBHostDevice *s = hostdev_list;
124 if (s->bus_num == bus_num && s->addr == addr)
131 typedef struct PendingURB {
132 struct usbdevfs_urb *urb;
134 struct PendingURB *next;
137 static PendingURB *pending_urbs = NULL;
139 static int add_pending_urb(struct usbdevfs_urb *urb)
141 PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
145 purb->next = pending_urbs;
152 static int del_pending_urb(struct usbdevfs_urb *urb)
154 PendingURB *purb = pending_urbs;
155 PendingURB *prev = NULL;
157 while (purb && purb->urb != urb) {
162 if (purb && purb->urb == urb) {
164 prev->next = purb->next;
166 pending_urbs = purb->next;
175 static PendingURB *get_pending_urb(struct usbdevfs_urb *urb)
177 PendingURB *purb = pending_urbs;
179 while (purb && purb->urb != urb) {
183 if (purb && purb->urb == urb) {
190 static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
192 int dev_descr_len, config_descr_len;
193 int interface, nb_interfaces, nb_configurations;
196 if (configuration == 0) /* address state - ignore */
200 dev_descr_len = dev->descr[0];
201 if (dev_descr_len > dev->descr_len)
203 nb_configurations = dev->descr[17];
206 while (i < dev->descr_len) {
208 printf("i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
209 dev->descr[i], dev->descr[i+1]);
211 if (dev->descr[i+1] != USB_DT_CONFIG) {
215 config_descr_len = dev->descr[i];
218 printf("config #%d need %d\n", dev->descr[i + 5], configuration);
221 if (configuration < 0 || configuration == dev->descr[i + 5])
224 i += config_descr_len;
227 if (i >= dev->descr_len) {
228 printf("usb_host: error - device has no matching configuration\n");
231 nb_interfaces = dev->descr[i + 4];
233 #ifdef USBDEVFS_DISCONNECT
234 /* earlier Linux 2.4 do not support that */
236 struct usbdevfs_ioctl ctrl;
237 for (interface = 0; interface < nb_interfaces; interface++) {
238 ctrl.ioctl_code = USBDEVFS_DISCONNECT;
239 ctrl.ifno = interface;
240 ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
241 if (ret < 0 && errno != ENODATA) {
242 perror("USBDEVFS_DISCONNECT");
249 /* XXX: only grab if all interfaces are free */
250 for (interface = 0; interface < nb_interfaces; interface++) {
251 ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
253 if (errno == EBUSY) {
255 "usb_host: warning - device already grabbed\n");
257 perror("USBDEVFS_CLAIMINTERFACE");
265 printf("usb_host: %d interfaces claimed for configuration %d\n",
266 nb_interfaces, configuration);
272 static void usb_host_handle_reset(USBDevice *dev)
275 USBHostDevice *s = (USBHostDevice *)dev;
276 /* USBDEVFS_RESET, but not the first time as it has already be
277 done by the host OS */
278 ioctl(s->fd, USBDEVFS_RESET);
282 static void usb_host_handle_destroy(USBDevice *dev)
284 USBHostDevice *s = (USBHostDevice *)dev;
286 qemu_del_timer(s->timer);
296 static int usb_linux_update_endp_table(USBHostDevice *s);
298 static int usb_host_handle_control(USBDevice *dev,
305 USBHostDevice *s = (USBHostDevice *)dev;
306 struct usb_ctrltransfer ct;
307 struct usbdevfs_setinterface si;
308 int intf_update_required = 0;
311 if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
312 /* specific SET_ADDRESS support */
315 } else if (request == ((USB_RECIP_INTERFACE << 8) |
316 USB_REQ_SET_INTERFACE)) {
317 /* set alternate setting for the interface */
318 si.interface = index;
319 si.altsetting = value;
320 ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
321 usb_linux_update_endp_table(s);
322 } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
324 printf("usb_host_handle_control: SET_CONFIGURATION request - "
325 "config %d\n", value & 0xff);
327 if (s->configuration != (value & 0xff)) {
328 s->configuration = (value & 0xff);
329 intf_update_required = 1;
334 ct.bRequestType = request >> 8;
335 ct.bRequest = request;
341 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
349 return USB_RET_STALL;
352 if (intf_update_required) {
354 printf("usb_host_handle_control: updating interfaces\n");
356 usb_host_update_interfaces(s, value & 0xff);
362 static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p);
364 static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
366 USBHostDevice *s = (USBHostDevice *)dev;
367 struct usbdevfs_bulktransfer bt;
369 uint8_t devep = p->devep;
371 if (s->endp_table[p->devep - 1].type == USBDEVFS_URB_TYPE_ISO) {
372 return usb_host_handle_isoch(dev, p);
375 /* XXX: optimize and handle all data types by looking at the
377 if (p->pid == USB_TOKEN_IN)
383 ret = ioctl(s->fd, USBDEVFS_BULK, &bt);
391 printf("handle_data: errno=%d\n", errno);
393 return USB_RET_STALL;
401 static void urb_completion_pipe_read(void *opaque)
403 USBHostDevice *s = opaque;
404 USBPacket *p = s->packet;
405 PendingURB *pending_urb = NULL;
406 struct usbdevfs_urb *purb = NULL;
409 len = read(s->pipe_fds[0], &pending_urb, sizeof(pending_urb));
410 if (len != sizeof(pending_urb)) {
411 printf("urb_completion: error reading pending_urb, len=%d\n", len);
415 /* FIXME: handle pending_urb->status */
416 del_pending_urb(pending_urb->urb);
423 ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
425 printf("urb_completion: REAPURBNDELAY ioctl=%d errno=%d\n",
431 if (purb == pending_urb->urb) {
432 printf("urb_completion: urb mismatch reaped=%p pending=%p\n",
437 p->len = purb->actual_length;
438 usb_packet_complete(p);
443 static void isoch_done(int signum, siginfo_t *info, void *context)
445 struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
446 USBHostDevice *s = (USBHostDevice *)urb->usercontext;
449 if (info->si_code != SI_ASYNCIO ||
450 info->si_signo != SIG_ISOCOMPLETE) {
454 purb = get_pending_urb(urb);
456 purb->status = info->si_errno;
457 write(s->pipe_fds[1], &purb, sizeof(purb));
462 static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p)
464 USBHostDevice *s = (USBHostDevice *)dev;
465 struct usbdevfs_urb *urb, *purb = NULL;
467 uint8_t devep = p->devep;
469 if (p->pid == USB_TOKEN_IN)
472 urb = qemu_mallocz(sizeof(struct usbdevfs_urb) +
473 sizeof(struct usbdevfs_iso_packet_desc));
475 printf("usb_host_handle_isoch: malloc failed\n");
479 urb->type = USBDEVFS_URB_TYPE_ISO;
480 urb->endpoint = devep;
482 urb->flags = USBDEVFS_URB_ISO_ASAP;
483 urb->buffer = p->data;
484 urb->buffer_length = p->len;
485 urb->actual_length = 0;
486 urb->start_frame = 0;
487 urb->error_count = 0;
489 urb->signr = SIG_ISOCOMPLETE;
493 urb->usercontext = s;
494 urb->number_of_packets = 1;
495 urb->iso_frame_desc[0].length = p->len;
496 urb->iso_frame_desc[0].actual_length = 0;
497 urb->iso_frame_desc[0].status = 0;
498 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
500 if (!add_pending_urb(urb)) {
501 printf("usb_host_handle_isoch: add_pending_urb failed %p\n", urb);
504 printf("usb_host_handle_isoch: SUBMITURB ioctl=%d errno=%d\n",
512 return USB_RET_STALL;
516 /* FIXME: handle urbs_ready together with sync io
517 * workaround for injecting the signaled urbs into current frame */
518 if (s->urbs_ready > 0) {
519 ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
521 ret = purb->actual_length;
528 return USB_RET_ASYNC;
530 ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
532 if (del_pending_urb(purb)) {
533 ret = purb->actual_length;
536 printf("usb_host_handle_isoch: del_pending_urb failed %p\n", purb);
540 printf("usb_host_handle_isoch: REAPURBNDELAY ioctl=%d errno=%d\n",
548 /* returns 1 on problem encountered or 0 for success */
549 static int usb_linux_update_endp_table(USBHostDevice *s)
551 uint8_t *descriptors;
552 uint8_t devep, type, configuration, alt_interface;
553 struct usb_ctrltransfer ct;
554 int interface, ret, length, i;
556 ct.bRequestType = USB_DIR_IN;
557 ct.bRequest = USB_REQ_GET_CONFIGURATION;
561 ct.data = &configuration;
564 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
566 perror("usb_linux_update_endp_table");
570 /* in address state */
571 if (configuration == 0)
574 /* get the desired configuration, interface, and endpoint descriptors
575 * from device description */
576 descriptors = &s->descr[18];
577 length = s->descr_len - 18;
580 if (descriptors[i + 1] != USB_DT_CONFIG ||
581 descriptors[i + 5] != configuration) {
582 printf("invalid descriptor data - configuration\n");
588 if (descriptors[i + 1] != USB_DT_INTERFACE ||
589 (descriptors[i + 1] == USB_DT_INTERFACE &&
590 descriptors[i + 4] == 0)) {
595 interface = descriptors[i + 2];
597 ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
598 ct.bRequest = USB_REQ_GET_INTERFACE;
600 ct.wIndex = interface;
602 ct.data = &alt_interface;
605 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
607 perror("usb_linux_update_endp_table");
611 /* the current interface descriptor is the active interface
612 * and has endpoints */
613 if (descriptors[i + 3] != alt_interface) {
618 /* advance to the endpoints */
619 while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
626 if (descriptors[i + 1] != USB_DT_ENDPOINT)
629 devep = descriptors[i + 2];
630 switch (descriptors[i + 3] & 0x3) {
632 type = USBDEVFS_URB_TYPE_CONTROL;
635 type = USBDEVFS_URB_TYPE_ISO;
638 type = USBDEVFS_URB_TYPE_BULK;
641 type = USBDEVFS_URB_TYPE_INTERRUPT;
644 printf("usb_host: malformed endpoint type\n");
645 type = USBDEVFS_URB_TYPE_BULK;
647 s->endp_table[(devep & 0xf) - 1].type = type;
655 static void usb_host_device_check(void *priv)
657 USBHostDevice *s = priv;
658 struct usbdevfs_connectinfo ci;
661 err = ioctl(s->fd, USBDEVFS_CONNECTINFO, &ci);
663 printf("usb device %d.%d disconnected\n", 0, s->dev.addr);
664 usb_device_del_addr(0, s->dev.addr);
668 qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
671 static USBDevice *usb_host_device_open_addr(int bus_num, int addr, const char *prod_name)
674 USBHostDevice *dev = NULL;
675 struct usbdevfs_connectinfo ci;
678 dev = qemu_mallocz(sizeof(USBHostDevice));
682 dev->bus_num = bus_num;
685 dev->timer = qemu_new_timer(rt_clock, usb_host_device_check, (void *) dev);
690 printf("usb_host_device_open %d.%d\n", bus_num, addr);
693 snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
695 fd = open(buf, O_RDWR | O_NONBLOCK);
701 /* read the device description */
702 dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
703 if (dev->descr_len <= 0) {
704 perror("usb_host_device_open: reading device data failed");
711 printf("=== begin dumping device descriptor data ===\n");
712 for (x = 0; x < dev->descr_len; x++)
713 printf("%02x ", dev->descr[x]);
714 printf("\n=== end dumping device descriptor data ===\n");
719 dev->configuration = 1;
721 /* XXX - do something about initial configuration */
722 if (!usb_host_update_interfaces(dev, -1))
725 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
727 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
732 printf("host USB device %d.%d grabbed\n", bus_num, addr);
735 ret = usb_linux_update_endp_table(dev);
740 dev->dev.speed = USB_SPEED_LOW;
742 dev->dev.speed = USB_SPEED_HIGH;
743 dev->dev.handle_packet = usb_generic_handle_packet;
745 dev->dev.handle_reset = usb_host_handle_reset;
746 dev->dev.handle_control = usb_host_handle_control;
747 dev->dev.handle_data = usb_host_handle_data;
748 dev->dev.handle_destroy = usb_host_handle_destroy;
750 if (!prod_name || prod_name[0] == '\0')
751 snprintf(dev->dev.devname, sizeof(dev->dev.devname),
752 "host:%d.%d", bus_num, addr);
754 pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
758 /* set up the signal handlers */
759 sigemptyset(&sigact.sa_mask);
760 sigact.sa_sigaction = isoch_done;
761 sigact.sa_flags = SA_SIGINFO;
762 sigact.sa_restorer = 0;
763 ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
765 perror("usb_host_device_open: sigaction failed");
769 if (pipe(dev->pipe_fds) < 0) {
770 perror("usb_host_device_open: pipe creation failed");
773 fcntl(dev->pipe_fds[0], F_SETFL, O_NONBLOCK | O_ASYNC);
774 fcntl(dev->pipe_fds[1], F_SETFL, O_NONBLOCK);
775 qemu_set_fd_handler(dev->pipe_fds[0], urb_completion_pipe_read, NULL, dev);
778 /* Start the timer to detect disconnect */
779 qemu_mod_timer(dev->timer, qemu_get_clock(rt_clock) + 1000);
784 return (USBDevice *)dev;
789 qemu_del_timer(dev->timer);
796 USBDevice *usb_host_device_open(const char *devname)
799 char product_name[PRODUCT_NAME_SZ];
801 if (usb_host_find_device(&bus_num, &addr,
802 product_name, sizeof(product_name),
806 if (hostdev_find(bus_num, addr)) {
807 printf("host usb device %d.%d is already open\n", bus_num, addr);
811 return usb_host_device_open_addr(bus_num, addr, product_name);
814 static int get_tag_value(char *buf, int buf_size,
815 const char *str, const char *tag,
816 const char *stopchars)
820 p = strstr(str, tag);
827 while (*p != '\0' && !strchr(stopchars, *p)) {
828 if ((q - buf) < (buf_size - 1))
836 static int usb_host_scan(void *opaque, USBScanFunc *func)
841 int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
843 char product_name[512];
845 f = fopen(USBDEVFS_PATH "/devices", "r");
847 term_printf("Could not open %s\n", USBDEVFS_PATH "/devices");
851 bus_num = addr = speed = class_id = product_id = vendor_id = 0;
854 if (fgets(line, sizeof(line), f) == NULL)
856 if (strlen(line) > 0)
857 line[strlen(line) - 1] = '\0';
858 if (line[0] == 'T' && line[1] == ':') {
859 if (device_count && (vendor_id || product_id)) {
860 /* New device. Add the previously discovered device. */
861 ret = func(opaque, bus_num, addr, class_id, vendor_id,
862 product_id, product_name, speed);
866 if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0)
869 if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0)
872 if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0)
874 if (!strcmp(buf, "480"))
875 speed = USB_SPEED_HIGH;
876 else if (!strcmp(buf, "1.5"))
877 speed = USB_SPEED_LOW;
879 speed = USB_SPEED_FULL;
880 product_name[0] = '\0';
885 } else if (line[0] == 'P' && line[1] == ':') {
886 if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0)
888 vendor_id = strtoul(buf, NULL, 16);
889 if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0)
891 product_id = strtoul(buf, NULL, 16);
892 } else if (line[0] == 'S' && line[1] == ':') {
893 if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0)
895 pstrcpy(product_name, sizeof(product_name), buf);
896 } else if (line[0] == 'D' && line[1] == ':') {
897 if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0)
899 class_id = strtoul(buf, NULL, 16);
903 if (device_count && (vendor_id || product_id)) {
904 /* Add the last device. */
905 ret = func(opaque, bus_num, addr, class_id, vendor_id,
906 product_id, product_name, speed);
913 struct USBAutoFilter {
914 struct USBAutoFilter *next;
921 static QEMUTimer *usb_auto_timer;
922 static struct USBAutoFilter *usb_auto_filter;
924 static int usb_host_auto_scan(void *opaque, int bus_num, int addr,
925 int class_id, int vendor_id, int product_id,
926 const char *product_name, int speed)
928 struct USBAutoFilter *f;
929 struct USBDevice *dev;
935 for (f = usb_auto_filter; f; f = f->next) {
936 // printf("Auto match: bus_num %d addr %d vid %d pid %d\n",
937 // bus_num, addr, vendor_id, product_id);
939 if (f->bus_num >= 0 && f->bus_num != bus_num)
942 if (f->addr >= 0 && f->addr != addr)
945 if (f->vendor_id >= 0 && f->vendor_id != vendor_id)
948 if (f->product_id >= 0 && f->product_id != product_id)
953 /* Allredy attached ? */
954 if (hostdev_find(bus_num, addr))
957 printf("Auto open: bus_num %d addr %d\n", bus_num, addr);
959 dev = usb_host_device_open_addr(bus_num, addr, product_name);
961 usb_device_add_dev(dev);
967 static void usb_host_auto_timer(void *unused)
969 usb_host_scan(NULL, usb_host_auto_scan);
970 qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
974 * Add autoconnect filter
975 * -1 means 'any' (device, vendor, etc)
977 static void usb_host_auto_add(int bus_num, int addr, int vendor_id, int product_id)
979 struct USBAutoFilter *f = qemu_mallocz(sizeof(*f));
981 printf("Failed to allocate auto filter\n");
985 f->bus_num = bus_num;
987 f->vendor_id = vendor_id;
988 f->product_id = product_id;
990 if (!usb_auto_filter) {
992 * First entry. Init and start the monitor.
993 * Right now we're using timer to check for new devices.
994 * If this turns out to be too expensive we can move that into a
997 usb_auto_timer = qemu_new_timer(rt_clock, usb_host_auto_timer, NULL);
998 if (!usb_auto_timer) {
999 printf("Failed to allocate timer\n");
1004 /* Check for new devices every two seconds */
1005 qemu_mod_timer(usb_auto_timer, qemu_get_clock(rt_clock) + 2000);
1008 printf("Auto filter: bus_num %d addr %d vid %d pid %d\n",
1009 bus_num, addr, vendor_id, product_id);
1011 f->next = usb_auto_filter;
1012 usb_auto_filter = f;
1015 typedef struct FindDeviceState {
1020 char product_name[PRODUCT_NAME_SZ];
1023 static int usb_host_find_device_scan(void *opaque, int bus_num, int addr,
1025 int vendor_id, int product_id,
1026 const char *product_name, int speed)
1028 FindDeviceState *s = opaque;
1029 if ((vendor_id == s->vendor_id &&
1030 product_id == s->product_id) ||
1031 (bus_num == s->bus_num &&
1033 pstrcpy(s->product_name, PRODUCT_NAME_SZ, product_name);
1034 s->bus_num = bus_num;
1043 'bus.addr' (decimal numbers) or
1044 'vendor_id:product_id' (hexa numbers) */
1045 static int usb_host_find_device(int *pbus_num, int *paddr,
1046 char *product_name, int product_name_size,
1047 const char *devname)
1053 p = strchr(devname, '.');
1055 *pbus_num = strtoul(devname, NULL, 0);
1057 if (*(p + 1) == '*') {
1058 usb_host_auto_add(*pbus_num, -1, -1, -1);
1062 *paddr = strtoul(p + 1, NULL, 0);
1063 fs.bus_num = *pbus_num;
1065 ret = usb_host_scan(&fs, usb_host_find_device_scan);
1067 pstrcpy(product_name, product_name_size, fs.product_name);
1070 p = strchr(devname, ':');
1072 fs.vendor_id = strtoul(devname, NULL, 16);
1074 if (*(p + 1) == '*') {
1075 usb_host_auto_add(-1, -1, fs.vendor_id, -1);
1079 fs.product_id = strtoul(p + 1, NULL, 16);
1080 ret = usb_host_scan(&fs, usb_host_find_device_scan);
1082 *pbus_num = fs.bus_num;
1084 pstrcpy(product_name, product_name_size, fs.product_name);
1091 /**********************/
1092 /* USB host device info */
1094 struct usb_class_info {
1096 const char *class_name;
1099 static const struct usb_class_info usb_class_info[] = {
1100 { USB_CLASS_AUDIO, "Audio"},
1101 { USB_CLASS_COMM, "Communication"},
1102 { USB_CLASS_HID, "HID"},
1103 { USB_CLASS_HUB, "Hub" },
1104 { USB_CLASS_PHYSICAL, "Physical" },
1105 { USB_CLASS_PRINTER, "Printer" },
1106 { USB_CLASS_MASS_STORAGE, "Storage" },
1107 { USB_CLASS_CDC_DATA, "Data" },
1108 { USB_CLASS_APP_SPEC, "Application Specific" },
1109 { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
1110 { USB_CLASS_STILL_IMAGE, "Still Image" },
1111 { USB_CLASS_CSCID, "Smart Card" },
1112 { USB_CLASS_CONTENT_SEC, "Content Security" },
1116 static const char *usb_class_str(uint8_t class)
1118 const struct usb_class_info *p;
1119 for(p = usb_class_info; p->class != -1; p++) {
1120 if (p->class == class)
1123 return p->class_name;
1126 static void usb_info_device(int bus_num, int addr, int class_id,
1127 int vendor_id, int product_id,
1128 const char *product_name,
1131 const char *class_str, *speed_str;
1137 case USB_SPEED_FULL:
1140 case USB_SPEED_HIGH:
1148 term_printf(" Device %d.%d, speed %s Mb/s\n",
1149 bus_num, addr, speed_str);
1150 class_str = usb_class_str(class_id);
1152 term_printf(" %s:", class_str);
1154 term_printf(" Class %02x:", class_id);
1155 term_printf(" USB device %04x:%04x", vendor_id, product_id);
1156 if (product_name[0] != '\0')
1157 term_printf(", %s", product_name);
1161 static int usb_host_info_device(void *opaque, int bus_num, int addr,
1163 int vendor_id, int product_id,
1164 const char *product_name,
1167 usb_info_device(bus_num, addr, class_id, vendor_id, product_id,
1168 product_name, speed);
1172 void usb_host_info(void)
1174 usb_host_scan(NULL, usb_host_info_device);
1182 void usb_host_info(void)
1184 term_printf("USB host devices not supported\n");
1187 /* XXX: modify configure to compile the right host driver */
1188 USBDevice *usb_host_device_open(const char *devname)