]> git.proxmox.com Git - qemu.git/blob - usb-linux.c
New '-bios' option, used to select an alternate BIOS image from bios_dir.
[qemu.git] / 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