]> git.proxmox.com Git - qemu.git/blame - usb-linux.c
usb-linux: Don't do perror when errno is not set
[qemu.git] / usb-linux.c
CommitLineData
bb36d470
FB
1/*
2 * Linux host USB redirector
3 *
4 * Copyright (c) 2005 Fabrice Bellard
5fafdf24 5 *
64838171
AL
6 * Copyright (c) 2008 Max Krasnyansky
7 * Support for host device auto connect & disconnect
5d0c5750 8 * Major rewrite to support fully async operation
4b096fc9 9 *
0f431527
AL
10 * Copyright 2008 TJ <linux@tjworld.net>
11 * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition
12 * to the legacy /proc/bus/usb USB device discovery and handling
13 *
bb36d470
FB
14 * Permission is hereby granted, free of charge, to any person obtaining a copy
15 * of this software and associated documentation files (the "Software"), to deal
16 * in the Software without restriction, including without limitation the rights
17 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18 * copies of the Software, and to permit persons to whom the Software is
19 * furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30 * THE SOFTWARE.
31 */
446ab128 32
87ecb68b 33#include "qemu-common.h"
1f3870ab 34#include "qemu-timer.h"
376253ec 35#include "monitor.h"
b373a63a 36#include "sysemu.h"
bb36d470 37
bb36d470
FB
38#include <dirent.h>
39#include <sys/ioctl.h>
bb36d470 40
446ab128
AL
41#include <linux/usbdevice_fs.h>
42#include <linux/version.h>
43#include "hw/usb.h"
bb36d470 44
d9cf1578
BS
45/* We redefine it to avoid version problems */
46struct usb_ctrltransfer {
47 uint8_t bRequestType;
48 uint8_t bRequest;
49 uint16_t wValue;
50 uint16_t wIndex;
51 uint16_t wLength;
52 uint32_t timeout;
53 void *data;
54};
55
5557d820 56typedef int USBScanFunc(void *opaque, int bus_num, int addr, char *port,
0f5160d1 57 int class_id, int vendor_id, int product_id,
a594cfbf 58 const char *product_name, int speed);
26a9e82a 59
0745eb1e 60//#define DEBUG
64838171
AL
61
62#ifdef DEBUG
d0f2c4c6 63#define DPRINTF printf
64838171 64#else
d0f2c4c6 65#define DPRINTF(...)
64838171 66#endif
bb36d470 67
5be8e1f2
BS
68#define USBDBG_DEVOPENED "husb: opened %s/devices\n"
69
0f431527 70#define USBPROCBUS_PATH "/proc/bus/usb"
1f6e24e7 71#define PRODUCT_NAME_SZ 32
3a4854b3 72#define MAX_ENDPOINTS 15
5557d820 73#define MAX_PORTLEN 16
0f431527
AL
74#define USBDEVBUS_PATH "/dev/bus/usb"
75#define USBSYSBUS_PATH "/sys/bus/usb"
76
77static char *usb_host_device_path;
78
79#define USB_FS_NONE 0
80#define USB_FS_PROC 1
81#define USB_FS_DEV 2
82#define USB_FS_SYS 3
83
84static int usb_fs_type;
bb36d470 85
b9dc033c 86/* endpoint association data */
060dc841
HG
87#define ISO_FRAME_DESC_PER_URB 32
88#define ISO_URB_COUNT 3
a0b5fece 89#define INVALID_EP_TYPE 255
060dc841 90
71138531
GH
91/* devio.c limits single requests to 16k */
92#define MAX_USBFS_BUFFER_SIZE 16384
93
060dc841
HG
94typedef struct AsyncURB AsyncURB;
95
b9dc033c
AZ
96struct endp_data {
97 uint8_t type;
64838171 98 uint8_t halted;
bb6d5498 99 uint8_t iso_started;
060dc841
HG
100 AsyncURB *iso_urb;
101 int iso_urb_idx;
bb6d5498 102 int iso_buffer_used;
060dc841 103 int max_packet_size;
b9dc033c
AZ
104};
105
26a9e82a
GH
106struct USBAutoFilter {
107 uint32_t bus_num;
108 uint32_t addr;
9056a297 109 char *port;
26a9e82a
GH
110 uint32_t vendor_id;
111 uint32_t product_id;
112};
113
bb36d470
FB
114typedef struct USBHostDevice {
115 USBDevice dev;
64838171
AL
116 int fd;
117
118 uint8_t descr[1024];
119 int descr_len;
120 int configuration;
446ab128 121 int ninterfaces;
24772c1e 122 int closing;
b373a63a 123 Notifier exit;
64838171 124
b9dc033c 125 struct endp_data endp_table[MAX_ENDPOINTS];
7a8fc83f 126 QLIST_HEAD(, AsyncURB) aurbs;
4b096fc9 127
4b096fc9
AL
128 /* Host side address */
129 int bus_num;
130 int addr;
5557d820 131 char port[MAX_PORTLEN];
26a9e82a 132 struct USBAutoFilter match;
4b096fc9 133
26a9e82a 134 QTAILQ_ENTRY(USBHostDevice) next;
bb36d470
FB
135} USBHostDevice;
136
26a9e82a
GH
137static QTAILQ_HEAD(, USBHostDevice) hostdevs = QTAILQ_HEAD_INITIALIZER(hostdevs);
138
139static int usb_host_close(USBHostDevice *dev);
140static int parse_filter(const char *spec, struct USBAutoFilter *f);
141static void usb_host_auto_check(void *unused);
2cc59d8c
HG
142static int usb_host_read_file(char *line, size_t line_size,
143 const char *device_file, const char *device_name);
26a9e82a 144
64838171
AL
145static int is_isoc(USBHostDevice *s, int ep)
146{
147 return s->endp_table[ep - 1].type == USBDEVFS_URB_TYPE_ISO;
148}
149
a0b5fece
HG
150static int is_valid(USBHostDevice *s, int ep)
151{
152 return s->endp_table[ep - 1].type != INVALID_EP_TYPE;
153}
154
64838171
AL
155static int is_halted(USBHostDevice *s, int ep)
156{
157 return s->endp_table[ep - 1].halted;
158}
159
160static void clear_halt(USBHostDevice *s, int ep)
161{
162 s->endp_table[ep - 1].halted = 0;
163}
164
165static void set_halt(USBHostDevice *s, int ep)
166{
167 s->endp_table[ep - 1].halted = 1;
168}
169
bb6d5498
HG
170static int is_iso_started(USBHostDevice *s, int ep)
171{
172 return s->endp_table[ep - 1].iso_started;
173}
174
175static void clear_iso_started(USBHostDevice *s, int ep)
176{
177 s->endp_table[ep - 1].iso_started = 0;
178}
179
180static void set_iso_started(USBHostDevice *s, int ep)
181{
182 s->endp_table[ep - 1].iso_started = 1;
183}
184
060dc841
HG
185static void set_iso_urb(USBHostDevice *s, int ep, AsyncURB *iso_urb)
186{
187 s->endp_table[ep - 1].iso_urb = iso_urb;
188}
189
190static AsyncURB *get_iso_urb(USBHostDevice *s, int ep)
191{
192 return s->endp_table[ep - 1].iso_urb;
193}
194
195static void set_iso_urb_idx(USBHostDevice *s, int ep, int i)
196{
197 s->endp_table[ep - 1].iso_urb_idx = i;
198}
199
200static int get_iso_urb_idx(USBHostDevice *s, int ep)
201{
202 return s->endp_table[ep - 1].iso_urb_idx;
203}
204
bb6d5498
HG
205static void set_iso_buffer_used(USBHostDevice *s, int ep, int i)
206{
207 s->endp_table[ep - 1].iso_buffer_used = i;
208}
209
210static int get_iso_buffer_used(USBHostDevice *s, int ep)
211{
212 return s->endp_table[ep - 1].iso_buffer_used;
213}
214
6dfcdccb
GH
215static void set_max_packet_size(USBHostDevice *s, int ep, uint8_t *descriptor)
216{
217 int raw = descriptor[4] + (descriptor[5] << 8);
218 int size, microframes;
219
220 size = raw & 0x7ff;
221 switch ((raw >> 11) & 3) {
222 case 1: microframes = 2; break;
223 case 2: microframes = 3; break;
224 default: microframes = 1; break;
225 }
226 DPRINTF("husb: max packet size: 0x%x -> %d x %d\n",
227 raw, microframes, size);
228 s->endp_table[ep - 1].max_packet_size = size * microframes;
229}
230
060dc841
HG
231static int get_max_packet_size(USBHostDevice *s, int ep)
232{
233 return s->endp_table[ep - 1].max_packet_size;
234}
235
2791104c 236/*
64838171 237 * Async URB state.
060dc841 238 * We always allocate iso packet descriptors even for bulk transfers
2791104c 239 * to simplify allocation and casts.
64838171 240 */
060dc841 241struct AsyncURB
64838171
AL
242{
243 struct usbdevfs_urb urb;
060dc841 244 struct usbdevfs_iso_packet_desc isocpd[ISO_FRAME_DESC_PER_URB];
7a8fc83f
GH
245 USBHostDevice *hdev;
246 QLIST_ENTRY(AsyncURB) next;
b9dc033c 247
060dc841 248 /* For regular async urbs */
64838171 249 USBPacket *packet;
71138531 250 int more; /* large transfer, more urbs follow */
060dc841
HG
251
252 /* For buffered iso handling */
253 int iso_frame_idx; /* -1 means in flight */
254};
b9dc033c 255
7a8fc83f 256static AsyncURB *async_alloc(USBHostDevice *s)
b9dc033c 257{
7a8fc83f
GH
258 AsyncURB *aurb = qemu_mallocz(sizeof(AsyncURB));
259 aurb->hdev = s;
260 QLIST_INSERT_HEAD(&s->aurbs, aurb, next);
261 return aurb;
b9dc033c
AZ
262}
263
64838171 264static void async_free(AsyncURB *aurb)
b9dc033c 265{
7a8fc83f 266 QLIST_REMOVE(aurb, next);
64838171
AL
267 qemu_free(aurb);
268}
b9dc033c 269
41c01ee7
GH
270static void do_disconnect(USBHostDevice *s)
271{
272 printf("husb: device %d.%d disconnected\n",
273 s->bus_num, s->addr);
274 usb_host_close(s);
275 usb_host_auto_check(NULL);
276}
277
64838171
AL
278static void async_complete(void *opaque)
279{
280 USBHostDevice *s = opaque;
281 AsyncURB *aurb;
282
283 while (1) {
2791104c 284 USBPacket *p;
b9dc033c 285
2791104c 286 int r = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &aurb);
64838171 287 if (r < 0) {
2791104c 288 if (errno == EAGAIN) {
64838171 289 return;
2791104c 290 }
24772c1e 291 if (errno == ENODEV && !s->closing) {
41c01ee7 292 do_disconnect(s);
64838171
AL
293 return;
294 }
295
d0f2c4c6 296 DPRINTF("husb: async. reap urb failed errno %d\n", errno);
64838171 297 return;
b9dc033c 298 }
64838171 299
2791104c 300 DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
64838171
AL
301 aurb, aurb->urb.status, aurb->urb.actual_length);
302
060dc841
HG
303 /* If this is a buffered iso urb mark it as complete and don't do
304 anything else (it is handled further in usb_host_handle_iso_data) */
305 if (aurb->iso_frame_idx == -1) {
306 if (aurb->urb.status == -EPIPE) {
307 set_halt(s, aurb->urb.endpoint & 0xf);
308 }
309 aurb->iso_frame_idx = 0;
310 continue;
311 }
312
313 p = aurb->packet;
314
2791104c 315 if (p) {
64838171
AL
316 switch (aurb->urb.status) {
317 case 0:
71138531 318 p->len += aurb->urb.actual_length;
64838171
AL
319 break;
320
321 case -EPIPE:
322 set_halt(s, p->devep);
2791104c
DA
323 p->len = USB_RET_STALL;
324 break;
dcc7e25f 325
64838171
AL
326 default:
327 p->len = USB_RET_NAK;
328 break;
329 }
330
50b7963e
HG
331 if (aurb->urb.type == USBDEVFS_URB_TYPE_CONTROL) {
332 usb_generic_async_ctrl_complete(&s->dev, p);
71138531 333 } else if (!aurb->more) {
50b7963e
HG
334 usb_packet_complete(&s->dev, p);
335 }
2791104c 336 }
64838171
AL
337
338 async_free(aurb);
b9dc033c 339 }
b9dc033c
AZ
340}
341
eb5e680a 342static void usb_host_async_cancel(USBDevice *dev, USBPacket *p)
b9dc033c 343{
eb5e680a 344 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
227ebeb5 345 AsyncURB *aurb;
b9dc033c 346
227ebeb5
GH
347 QLIST_FOREACH(aurb, &s->aurbs, next) {
348 if (p != aurb->packet) {
349 continue;
350 }
64838171 351
227ebeb5 352 DPRINTF("husb: async cancel: packet %p, aurb %p\n", p, aurb);
b9dc033c 353
227ebeb5
GH
354 /* Mark it as dead (see async_complete above) */
355 aurb->packet = NULL;
356
357 int r = ioctl(s->fd, USBDEVFS_DISCARDURB, aurb);
358 if (r < 0) {
359 DPRINTF("husb: async. discard urb failed errno %d\n", errno);
360 }
b9dc033c 361 }
b9dc033c
AZ
362}
363
446ab128 364static int usb_host_claim_interfaces(USBHostDevice *dev, int configuration)
b9dc033c 365{
41c01ee7 366 const char *op = NULL;
b9dc033c 367 int dev_descr_len, config_descr_len;
d4c4e6fd 368 int interface, nb_interfaces;
b9dc033c
AZ
369 int ret, i;
370
371 if (configuration == 0) /* address state - ignore */
372 return 1;
373
d0f2c4c6 374 DPRINTF("husb: claiming interfaces. config %d\n", configuration);
446ab128 375
b9dc033c
AZ
376 i = 0;
377 dev_descr_len = dev->descr[0];
2791104c 378 if (dev_descr_len > dev->descr_len) {
61c1117f
HG
379 fprintf(stderr, "husb: update iface failed. descr too short\n");
380 return 0;
2791104c 381 }
b9dc033c
AZ
382
383 i += dev_descr_len;
384 while (i < dev->descr_len) {
2791104c
DA
385 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
386 i, dev->descr_len,
b9dc033c 387 dev->descr[i], dev->descr[i+1]);
64838171 388
b9dc033c
AZ
389 if (dev->descr[i+1] != USB_DT_CONFIG) {
390 i += dev->descr[i];
391 continue;
392 }
393 config_descr_len = dev->descr[i];
394
2791104c 395 printf("husb: config #%d need %d\n", dev->descr[i + 5], configuration);
1f3870ab 396
446ab128
AL
397 if (configuration < 0 || configuration == dev->descr[i + 5]) {
398 configuration = dev->descr[i + 5];
b9dc033c 399 break;
446ab128 400 }
b9dc033c
AZ
401
402 i += config_descr_len;
403 }
404
405 if (i >= dev->descr_len) {
2791104c
DA
406 fprintf(stderr,
407 "husb: update iface failed. no matching configuration\n");
61c1117f 408 return 0;
b9dc033c
AZ
409 }
410 nb_interfaces = dev->descr[i + 4];
411
412#ifdef USBDEVFS_DISCONNECT
413 /* earlier Linux 2.4 do not support that */
414 {
415 struct usbdevfs_ioctl ctrl;
416 for (interface = 0; interface < nb_interfaces; interface++) {
417 ctrl.ioctl_code = USBDEVFS_DISCONNECT;
418 ctrl.ifno = interface;
021730f7 419 ctrl.data = 0;
41c01ee7 420 op = "USBDEVFS_DISCONNECT";
b9dc033c
AZ
421 ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
422 if (ret < 0 && errno != ENODATA) {
b9dc033c
AZ
423 goto fail;
424 }
425 }
426 }
427#endif
428
429 /* XXX: only grab if all interfaces are free */
430 for (interface = 0; interface < nb_interfaces; interface++) {
41c01ee7 431 op = "USBDEVFS_CLAIMINTERFACE";
b9dc033c
AZ
432 ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
433 if (ret < 0) {
434 if (errno == EBUSY) {
64838171 435 printf("husb: update iface. device already grabbed\n");
b9dc033c 436 } else {
64838171 437 perror("husb: failed to claim interface");
b9dc033c 438 }
41c01ee7 439 goto fail;
b9dc033c
AZ
440 }
441 }
442
64838171 443 printf("husb: %d interfaces claimed for configuration %d\n",
b9dc033c 444 nb_interfaces, configuration);
b9dc033c 445
446ab128
AL
446 dev->ninterfaces = nb_interfaces;
447 dev->configuration = configuration;
448 return 1;
41c01ee7
GH
449
450fail:
451 if (errno == ENODEV) {
452 do_disconnect(dev);
453 }
454 perror(op);
455 return 0;
446ab128
AL
456}
457
458static int usb_host_release_interfaces(USBHostDevice *s)
459{
460 int ret, i;
461
d0f2c4c6 462 DPRINTF("husb: releasing interfaces\n");
446ab128
AL
463
464 for (i = 0; i < s->ninterfaces; i++) {
465 ret = ioctl(s->fd, USBDEVFS_RELEASEINTERFACE, &i);
466 if (ret < 0) {
467 perror("husb: failed to release interface");
468 return 0;
469 }
470 }
471
b9dc033c
AZ
472 return 1;
473}
474
059809e4 475static void usb_host_handle_reset(USBDevice *dev)
bb36d470 476{
26a9e82a 477 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
64838171 478
d0f2c4c6 479 DPRINTF("husb: reset device %u.%u\n", s->bus_num, s->addr);
64838171 480
bb36d470 481 ioctl(s->fd, USBDEVFS_RESET);
446ab128
AL
482
483 usb_host_claim_interfaces(s, s->configuration);
5fafdf24 484}
bb36d470 485
059809e4
FB
486static void usb_host_handle_destroy(USBDevice *dev)
487{
488 USBHostDevice *s = (USBHostDevice *)dev;
489
26a9e82a
GH
490 usb_host_close(s);
491 QTAILQ_REMOVE(&hostdevs, s, next);
b373a63a 492 qemu_remove_exit_notifier(&s->exit);
059809e4
FB
493}
494
b9dc033c
AZ
495static int usb_linux_update_endp_table(USBHostDevice *s);
496
060dc841
HG
497/* iso data is special, we need to keep enough urbs in flight to make sure
498 that the controller never runs out of them, otherwise the device will
499 likely suffer a buffer underrun / overrun. */
500static AsyncURB *usb_host_alloc_iso(USBHostDevice *s, uint8_t ep, int in)
501{
502 AsyncURB *aurb;
503 int i, j, len = get_max_packet_size(s, ep);
504
505 aurb = qemu_mallocz(ISO_URB_COUNT * sizeof(*aurb));
506 for (i = 0; i < ISO_URB_COUNT; i++) {
507 aurb[i].urb.endpoint = ep;
508 aurb[i].urb.buffer_length = ISO_FRAME_DESC_PER_URB * len;
509 aurb[i].urb.buffer = qemu_malloc(aurb[i].urb.buffer_length);
510 aurb[i].urb.type = USBDEVFS_URB_TYPE_ISO;
511 aurb[i].urb.flags = USBDEVFS_URB_ISO_ASAP;
512 aurb[i].urb.number_of_packets = ISO_FRAME_DESC_PER_URB;
513 for (j = 0 ; j < ISO_FRAME_DESC_PER_URB; j++)
514 aurb[i].urb.iso_frame_desc[j].length = len;
515 if (in) {
516 aurb[i].urb.endpoint |= 0x80;
517 /* Mark as fully consumed (idle) */
518 aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB;
519 }
520 }
521 set_iso_urb(s, ep, aurb);
522
523 return aurb;
524}
525
526static void usb_host_stop_n_free_iso(USBHostDevice *s, uint8_t ep)
527{
528 AsyncURB *aurb;
529 int i, ret, killed = 0, free = 1;
530
531 aurb = get_iso_urb(s, ep);
532 if (!aurb) {
533 return;
534 }
535
536 for (i = 0; i < ISO_URB_COUNT; i++) {
537 /* in flight? */
538 if (aurb[i].iso_frame_idx == -1) {
539 ret = ioctl(s->fd, USBDEVFS_DISCARDURB, &aurb[i]);
540 if (ret < 0) {
541 printf("husb: discard isoc in urb failed errno %d\n", errno);
542 free = 0;
543 continue;
544 }
545 killed++;
546 }
547 }
548
549 /* Make sure any urbs we've killed are reaped before we free them */
550 if (killed) {
551 async_complete(s);
552 }
553
554 for (i = 0; i < ISO_URB_COUNT; i++) {
555 qemu_free(aurb[i].urb.buffer);
556 }
557
558 if (free)
559 qemu_free(aurb);
560 else
561 printf("husb: leaking iso urbs because of discard failure\n");
562 set_iso_urb(s, ep, NULL);
bb6d5498
HG
563 set_iso_urb_idx(s, ep, 0);
564 clear_iso_started(s, ep);
060dc841
HG
565}
566
567static int urb_status_to_usb_ret(int status)
568{
569 switch (status) {
570 case -EPIPE:
571 return USB_RET_STALL;
572 default:
573 return USB_RET_NAK;
574 }
575}
576
bb6d5498 577static int usb_host_handle_iso_data(USBHostDevice *s, USBPacket *p, int in)
060dc841
HG
578{
579 AsyncURB *aurb;
bb6d5498 580 int i, j, ret, max_packet_size, offset, len = 0;
975f2998
HG
581
582 max_packet_size = get_max_packet_size(s, p->devep);
583 if (max_packet_size == 0)
584 return USB_RET_NAK;
060dc841
HG
585
586 aurb = get_iso_urb(s, p->devep);
587 if (!aurb) {
bb6d5498 588 aurb = usb_host_alloc_iso(s, p->devep, in);
060dc841
HG
589 }
590
591 i = get_iso_urb_idx(s, p->devep);
592 j = aurb[i].iso_frame_idx;
593 if (j >= 0 && j < ISO_FRAME_DESC_PER_URB) {
bb6d5498
HG
594 if (in) {
595 /* Check urb status */
596 if (aurb[i].urb.status) {
597 len = urb_status_to_usb_ret(aurb[i].urb.status);
598 /* Move to the next urb */
599 aurb[i].iso_frame_idx = ISO_FRAME_DESC_PER_URB - 1;
600 /* Check frame status */
601 } else if (aurb[i].urb.iso_frame_desc[j].status) {
602 len = urb_status_to_usb_ret(
603 aurb[i].urb.iso_frame_desc[j].status);
604 /* Check the frame fits */
605 } else if (aurb[i].urb.iso_frame_desc[j].actual_length > p->len) {
606 printf("husb: received iso data is larger then packet\n");
607 len = USB_RET_NAK;
608 /* All good copy data over */
609 } else {
610 len = aurb[i].urb.iso_frame_desc[j].actual_length;
611 memcpy(p->data,
612 aurb[i].urb.buffer +
613 j * aurb[i].urb.iso_frame_desc[0].length,
614 len);
615 }
060dc841 616 } else {
bb6d5498
HG
617 len = p->len;
618 offset = (j == 0) ? 0 : get_iso_buffer_used(s, p->devep);
619
620 /* Check the frame fits */
621 if (len > max_packet_size) {
622 printf("husb: send iso data is larger then max packet size\n");
623 return USB_RET_NAK;
624 }
625
626 /* All good copy data over */
627 memcpy(aurb[i].urb.buffer + offset, p->data, len);
628 aurb[i].urb.iso_frame_desc[j].length = len;
629 offset += len;
630 set_iso_buffer_used(s, p->devep, offset);
631
632 /* Start the stream once we have buffered enough data */
633 if (!is_iso_started(s, p->devep) && i == 1 && j == 8) {
634 set_iso_started(s, p->devep);
635 }
060dc841
HG
636 }
637 aurb[i].iso_frame_idx++;
638 if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
639 i = (i + 1) % ISO_URB_COUNT;
640 set_iso_urb_idx(s, p->devep, i);
641 }
bb6d5498
HG
642 } else {
643 if (in) {
644 set_iso_started(s, p->devep);
645 } else {
646 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
647 }
060dc841
HG
648 }
649
bb6d5498
HG
650 if (is_iso_started(s, p->devep)) {
651 /* (Re)-submit all fully consumed / filled urbs */
652 for (i = 0; i < ISO_URB_COUNT; i++) {
653 if (aurb[i].iso_frame_idx == ISO_FRAME_DESC_PER_URB) {
654 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, &aurb[i]);
655 if (ret < 0) {
656 printf("husb error submitting iso urb %d: %d\n", i, errno);
657 if (!in || len == 0) {
658 switch(errno) {
659 case ETIMEDOUT:
660 len = USB_RET_NAK;
0225e254 661 break;
bb6d5498
HG
662 case EPIPE:
663 default:
664 len = USB_RET_STALL;
665 }
060dc841 666 }
bb6d5498 667 break;
060dc841 668 }
bb6d5498 669 aurb[i].iso_frame_idx = -1;
060dc841 670 }
060dc841
HG
671 }
672 }
673
674 return len;
675}
676
50b7963e 677static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
bb36d470 678{
50b7963e 679 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
64838171 680 struct usbdevfs_urb *urb;
446ab128 681 AsyncURB *aurb;
71138531
GH
682 int ret, rem;
683 uint8_t *pbuf;
060dc841 684 uint8_t ep;
b9dc033c 685
a0b5fece
HG
686 if (!is_valid(s, p->devep)) {
687 return USB_RET_NAK;
688 }
689
2791104c 690 if (p->pid == USB_TOKEN_IN) {
060dc841 691 ep = p->devep | 0x80;
2791104c 692 } else {
060dc841 693 ep = p->devep;
2791104c 694 }
64838171
AL
695
696 if (is_halted(s, p->devep)) {
060dc841 697 ret = ioctl(s->fd, USBDEVFS_CLEAR_HALT, &ep);
64838171 698 if (ret < 0) {
2791104c 699 DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
060dc841 700 ep, errno);
bb36d470 701 return USB_RET_NAK;
bb36d470 702 }
64838171 703 clear_halt(s, p->devep);
4d043a09
AZ
704 }
705
bb6d5498
HG
706 if (is_isoc(s, p->devep)) {
707 return usb_host_handle_iso_data(s, p, p->pid == USB_TOKEN_IN);
708 }
060dc841 709
71138531
GH
710 rem = p->len;
711 pbuf = p->data;
712 p->len = 0;
713 while (rem) {
714 aurb = async_alloc(s);
715 aurb->packet = p;
716
717 urb = &aurb->urb;
718 urb->endpoint = ep;
719 urb->type = USBDEVFS_URB_TYPE_BULK;
720 urb->usercontext = s;
721 urb->buffer = pbuf;
722
723 if (rem > MAX_USBFS_BUFFER_SIZE) {
724 urb->buffer_length = MAX_USBFS_BUFFER_SIZE;
725 aurb->more = 1;
726 } else {
727 urb->buffer_length = rem;
728 aurb->more = 0;
729 }
730 pbuf += urb->buffer_length;
731 rem -= urb->buffer_length;
b9dc033c 732
71138531 733 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
b9dc033c 734
71138531
GH
735 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
736 urb->endpoint, urb->buffer_length, aurb->more, p, aurb);
b9dc033c 737
71138531
GH
738 if (ret < 0) {
739 DPRINTF("husb: submit failed. errno %d\n", errno);
740 async_free(aurb);
b9dc033c 741
71138531
GH
742 switch(errno) {
743 case ETIMEDOUT:
744 return USB_RET_NAK;
745 case EPIPE:
746 default:
747 return USB_RET_STALL;
748 }
b9dc033c
AZ
749 }
750 }
64838171 751
b9dc033c 752 return USB_RET_ASYNC;
b9dc033c
AZ
753}
754
446ab128
AL
755static int ctrl_error(void)
756{
2791104c 757 if (errno == ETIMEDOUT) {
446ab128 758 return USB_RET_NAK;
2791104c 759 } else {
446ab128 760 return USB_RET_STALL;
2791104c 761 }
446ab128
AL
762}
763
764static int usb_host_set_address(USBHostDevice *s, int addr)
765{
d0f2c4c6 766 DPRINTF("husb: ctrl set addr %u\n", addr);
446ab128
AL
767 s->dev.addr = addr;
768 return 0;
769}
770
771static int usb_host_set_config(USBHostDevice *s, int config)
772{
773 usb_host_release_interfaces(s);
774
775 int ret = ioctl(s->fd, USBDEVFS_SETCONFIGURATION, &config);
2791104c 776
d0f2c4c6 777 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config, ret, errno);
2791104c
DA
778
779 if (ret < 0) {
446ab128 780 return ctrl_error();
2791104c 781 }
446ab128
AL
782 usb_host_claim_interfaces(s, config);
783 return 0;
784}
785
786static int usb_host_set_interface(USBHostDevice *s, int iface, int alt)
787{
788 struct usbdevfs_setinterface si;
060dc841
HG
789 int i, ret;
790
3a4854b3 791 for (i = 1; i <= MAX_ENDPOINTS; i++) {
060dc841
HG
792 if (is_isoc(s, i)) {
793 usb_host_stop_n_free_iso(s, i);
794 }
795 }
446ab128
AL
796
797 si.interface = iface;
798 si.altsetting = alt;
799 ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
446ab128 800
2791104c
DA
801 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
802 iface, alt, ret, errno);
803
804 if (ret < 0) {
805 return ctrl_error();
806 }
446ab128
AL
807 usb_linux_update_endp_table(s);
808 return 0;
809}
810
50b7963e
HG
811static int usb_host_handle_control(USBDevice *dev, USBPacket *p,
812 int request, int value, int index, int length, uint8_t *data)
446ab128 813{
50b7963e 814 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
446ab128
AL
815 struct usbdevfs_urb *urb;
816 AsyncURB *aurb;
50b7963e 817 int ret;
446ab128 818
2791104c 819 /*
446ab128
AL
820 * Process certain standard device requests.
821 * These are infrequent and are processed synchronously.
822 */
446ab128 823
50b7963e 824 /* Note request is (bRequestType << 8) | bRequest */
d0f2c4c6 825 DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
50b7963e 826 request >> 8, request & 0xff, value, index, length);
446ab128 827
50b7963e
HG
828 switch (request) {
829 case DeviceOutRequest | USB_REQ_SET_ADDRESS:
830 return usb_host_set_address(s, value);
446ab128 831
50b7963e
HG
832 case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
833 return usb_host_set_config(s, value & 0xff);
446ab128 834
50b7963e 835 case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
446ab128 836 return usb_host_set_interface(s, index, value);
2791104c 837 }
446ab128
AL
838
839 /* The rest are asynchronous */
840
50b7963e
HG
841 if (length > sizeof(dev->data_buf)) {
842 fprintf(stderr, "husb: ctrl buffer too small (%d > %zu)\n",
843 length, sizeof(dev->data_buf));
b2e3b6e9 844 return USB_RET_STALL;
c4c0e236
JP
845 }
846
7a8fc83f 847 aurb = async_alloc(s);
446ab128
AL
848 aurb->packet = p;
849
2791104c 850 /*
446ab128
AL
851 * Setup ctrl transfer.
852 *
a0102082 853 * s->ctrl is laid out such that data buffer immediately follows
446ab128 854 * 'req' struct which is exactly what usbdevfs expects.
2791104c 855 */
446ab128
AL
856 urb = &aurb->urb;
857
858 urb->type = USBDEVFS_URB_TYPE_CONTROL;
859 urb->endpoint = p->devep;
860
50b7963e
HG
861 urb->buffer = &dev->setup_buf;
862 urb->buffer_length = length + 8;
446ab128
AL
863
864 urb->usercontext = s;
865
866 ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
867
d0f2c4c6 868 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb->buffer_length, aurb);
446ab128
AL
869
870 if (ret < 0) {
d0f2c4c6 871 DPRINTF("husb: submit failed. errno %d\n", errno);
446ab128
AL
872 async_free(aurb);
873
874 switch(errno) {
875 case ETIMEDOUT:
876 return USB_RET_NAK;
877 case EPIPE:
878 default:
879 return USB_RET_STALL;
880 }
881 }
882
446ab128
AL
883 return USB_RET_ASYNC;
884}
885
71d71bbd 886static int usb_linux_get_configuration(USBHostDevice *s)
b9dc033c 887{
71d71bbd 888 uint8_t configuration;
e41b3910 889 struct usb_ctrltransfer ct;
71d71bbd 890 int ret;
b9dc033c 891
2cc59d8c
HG
892 if (usb_fs_type == USB_FS_SYS) {
893 char device_name[32], line[1024];
894 int configuration;
895
5557d820 896 sprintf(device_name, "%d-%s", s->bus_num, s->port);
2cc59d8c
HG
897
898 if (!usb_host_read_file(line, sizeof(line), "bConfigurationValue",
899 device_name)) {
900 goto usbdevfs;
901 }
902 if (sscanf(line, "%d", &configuration) != 1) {
903 goto usbdevfs;
904 }
905 return configuration;
906 }
907
908usbdevfs:
b9dc033c
AZ
909 ct.bRequestType = USB_DIR_IN;
910 ct.bRequest = USB_REQ_GET_CONFIGURATION;
911 ct.wValue = 0;
912 ct.wIndex = 0;
913 ct.wLength = 1;
914 ct.data = &configuration;
915 ct.timeout = 50;
916
917 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
918 if (ret < 0) {
71d71bbd
HG
919 perror("usb_linux_get_configuration");
920 return -1;
b9dc033c
AZ
921 }
922
923 /* in address state */
2791104c 924 if (configuration == 0) {
71d71bbd 925 return -1;
2791104c 926 }
b9dc033c 927
71d71bbd
HG
928 return configuration;
929}
930
ed3a328d
HG
931static uint8_t usb_linux_get_alt_setting(USBHostDevice *s,
932 uint8_t configuration, uint8_t interface)
933{
934 uint8_t alt_setting;
935 struct usb_ctrltransfer ct;
936 int ret;
937
c43831fb
HG
938 if (usb_fs_type == USB_FS_SYS) {
939 char device_name[64], line[1024];
940 int alt_setting;
941
5557d820 942 sprintf(device_name, "%d-%s:%d.%d", s->bus_num, s->port,
c43831fb
HG
943 (int)configuration, (int)interface);
944
945 if (!usb_host_read_file(line, sizeof(line), "bAlternateSetting",
946 device_name)) {
947 goto usbdevfs;
948 }
949 if (sscanf(line, "%d", &alt_setting) != 1) {
950 goto usbdevfs;
951 }
952 return alt_setting;
953 }
954
955usbdevfs:
ed3a328d
HG
956 ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
957 ct.bRequest = USB_REQ_GET_INTERFACE;
958 ct.wValue = 0;
959 ct.wIndex = interface;
960 ct.wLength = 1;
961 ct.data = &alt_setting;
962 ct.timeout = 50;
963 ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
964 if (ret < 0) {
965 /* Assume alt 0 on error */
966 return 0;
967 }
968
969 return alt_setting;
970}
971
71d71bbd
HG
972/* returns 1 on problem encountered or 0 for success */
973static int usb_linux_update_endp_table(USBHostDevice *s)
974{
975 uint8_t *descriptors;
976 uint8_t devep, type, configuration, alt_interface;
ed3a328d 977 int interface, length, i;
71d71bbd 978
a0b5fece
HG
979 for (i = 0; i < MAX_ENDPOINTS; i++)
980 s->endp_table[i].type = INVALID_EP_TYPE;
981
71d71bbd
HG
982 i = usb_linux_get_configuration(s);
983 if (i < 0)
984 return 1;
985 configuration = i;
986
b9dc033c
AZ
987 /* get the desired configuration, interface, and endpoint descriptors
988 * from device description */
989 descriptors = &s->descr[18];
990 length = s->descr_len - 18;
991 i = 0;
992
993 if (descriptors[i + 1] != USB_DT_CONFIG ||
994 descriptors[i + 5] != configuration) {
d0f2c4c6 995 DPRINTF("invalid descriptor data - configuration\n");
b9dc033c
AZ
996 return 1;
997 }
998 i += descriptors[i];
999
1000 while (i < length) {
1001 if (descriptors[i + 1] != USB_DT_INTERFACE ||
1002 (descriptors[i + 1] == USB_DT_INTERFACE &&
1003 descriptors[i + 4] == 0)) {
1004 i += descriptors[i];
1005 continue;
1006 }
1007
1008 interface = descriptors[i + 2];
ed3a328d 1009 alt_interface = usb_linux_get_alt_setting(s, configuration, interface);
b9dc033c
AZ
1010
1011 /* the current interface descriptor is the active interface
1012 * and has endpoints */
1013 if (descriptors[i + 3] != alt_interface) {
1014 i += descriptors[i];
1015 continue;
1016 }
1017
1018 /* advance to the endpoints */
2791104c 1019 while (i < length && descriptors[i +1] != USB_DT_ENDPOINT) {
b9dc033c 1020 i += descriptors[i];
2791104c 1021 }
b9dc033c
AZ
1022
1023 if (i >= length)
1024 break;
1025
1026 while (i < length) {
2791104c 1027 if (descriptors[i + 1] != USB_DT_ENDPOINT) {
b9dc033c 1028 break;
2791104c 1029 }
b9dc033c
AZ
1030
1031 devep = descriptors[i + 2];
1032 switch (descriptors[i + 3] & 0x3) {
1033 case 0x00:
1034 type = USBDEVFS_URB_TYPE_CONTROL;
1035 break;
1036 case 0x01:
1037 type = USBDEVFS_URB_TYPE_ISO;
6dfcdccb 1038 set_max_packet_size(s, (devep & 0xf), descriptors + i);
b9dc033c
AZ
1039 break;
1040 case 0x02:
1041 type = USBDEVFS_URB_TYPE_BULK;
1042 break;
1043 case 0x03:
1044 type = USBDEVFS_URB_TYPE_INTERRUPT;
1045 break;
ddbda432
AL
1046 default:
1047 DPRINTF("usb_host: malformed endpoint type\n");
1048 type = USBDEVFS_URB_TYPE_BULK;
b9dc033c
AZ
1049 }
1050 s->endp_table[(devep & 0xf) - 1].type = type;
64838171 1051 s->endp_table[(devep & 0xf) - 1].halted = 0;
b9dc033c
AZ
1052
1053 i += descriptors[i];
1054 }
1055 }
1056 return 0;
1057}
1058
26a9e82a 1059static int usb_host_open(USBHostDevice *dev, int bus_num,
3991c35e 1060 int addr, char *port, const char *prod_name, int speed)
bb36d470 1061{
b9dc033c 1062 int fd = -1, ret;
a594cfbf 1063 char buf[1024];
1f3870ab 1064
2791104c 1065 if (dev->fd != -1) {
26a9e82a 1066 goto fail;
2791104c 1067 }
64838171 1068 printf("husb: open device %d.%d\n", bus_num, addr);
3b46e624 1069
0f431527
AL
1070 if (!usb_host_device_path) {
1071 perror("husb: USB Host Device Path not set");
1072 goto fail;
1073 }
1074 snprintf(buf, sizeof(buf), "%s/%03d/%03d", usb_host_device_path,
a594cfbf 1075 bus_num, addr);
b9dc033c 1076 fd = open(buf, O_RDWR | O_NONBLOCK);
bb36d470 1077 if (fd < 0) {
a594cfbf 1078 perror(buf);
1f3870ab 1079 goto fail;
bb36d470 1080 }
d0f2c4c6 1081 DPRINTF("husb: opened %s\n", buf);
bb36d470 1082
806b6024
GH
1083 dev->bus_num = bus_num;
1084 dev->addr = addr;
5557d820 1085 strcpy(dev->port, port);
22f84e73 1086 dev->fd = fd;
806b6024 1087
b9dc033c
AZ
1088 /* read the device description */
1089 dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
1090 if (dev->descr_len <= 0) {
64838171 1091 perror("husb: reading device data failed");
bb36d470
FB
1092 goto fail;
1093 }
3b46e624 1094
b9dc033c 1095#ifdef DEBUG
868bfe2b 1096 {
b9dc033c
AZ
1097 int x;
1098 printf("=== begin dumping device descriptor data ===\n");
2791104c 1099 for (x = 0; x < dev->descr_len; x++) {
b9dc033c 1100 printf("%02x ", dev->descr[x]);
2791104c 1101 }
b9dc033c 1102 printf("\n=== end dumping device descriptor data ===\n");
bb36d470 1103 }
a594cfbf
FB
1104#endif
1105
b9dc033c 1106
2791104c
DA
1107 /*
1108 * Initial configuration is -1 which makes us claim first
446ab128 1109 * available config. We used to start with 1, which does not
2791104c 1110 * always work. I've seen devices where first config starts
446ab128
AL
1111 * with 2.
1112 */
2791104c 1113 if (!usb_host_claim_interfaces(dev, -1)) {
b9dc033c 1114 goto fail;
2791104c 1115 }
bb36d470 1116
b9dc033c 1117 ret = usb_linux_update_endp_table(dev);
2791104c 1118 if (ret) {
bb36d470 1119 goto fail;
2791104c 1120 }
b9dc033c 1121
3991c35e
HG
1122 if (speed == -1) {
1123 struct usbdevfs_connectinfo ci;
1124
1125 ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
1126 if (ret < 0) {
1127 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1128 goto fail;
1129 }
1130
1131 if (ci.slow) {
1132 speed = USB_SPEED_LOW;
1133 } else {
1134 speed = USB_SPEED_HIGH;
1135 }
2791104c 1136 }
3991c35e
HG
1137 dev->dev.speed = speed;
1138
1139 printf("husb: grabbed usb device %d.%d\n", bus_num, addr);
bb36d470 1140
2791104c 1141 if (!prod_name || prod_name[0] == '\0') {
0fe6d12e 1142 snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
4b096fc9 1143 "host:%d.%d", bus_num, addr);
2791104c 1144 } else {
0fe6d12e 1145 pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
4b096fc9 1146 prod_name);
2791104c 1147 }
1f6e24e7 1148
64838171
AL
1149 /* USB devio uses 'write' flag to check for async completions */
1150 qemu_set_fd_handler(dev->fd, NULL, async_complete, dev);
1f3870ab 1151
26a9e82a
GH
1152 usb_device_attach(&dev->dev);
1153 return 0;
4b096fc9 1154
b9dc033c 1155fail:
26a9e82a 1156 dev->fd = -1;
2791104c 1157 if (fd != -1) {
806b6024 1158 close(fd);
2791104c 1159 }
26a9e82a
GH
1160 return -1;
1161}
1162
1163static int usb_host_close(USBHostDevice *dev)
1164{
060dc841
HG
1165 int i;
1166
2791104c 1167 if (dev->fd == -1) {
26a9e82a 1168 return -1;
2791104c 1169 }
26a9e82a
GH
1170
1171 qemu_set_fd_handler(dev->fd, NULL, NULL, NULL);
1172 dev->closing = 1;
3a4854b3 1173 for (i = 1; i <= MAX_ENDPOINTS; i++) {
060dc841
HG
1174 if (is_isoc(dev, i)) {
1175 usb_host_stop_n_free_iso(dev, i);
1176 }
1177 }
26a9e82a
GH
1178 async_complete(dev);
1179 dev->closing = 0;
1180 usb_device_detach(&dev->dev);
00ff227a 1181 ioctl(dev->fd, USBDEVFS_RESET);
26a9e82a
GH
1182 close(dev->fd);
1183 dev->fd = -1;
1184 return 0;
1185}
1186
b373a63a
SH
1187static void usb_host_exit_notifier(struct Notifier* n)
1188{
1189 USBHostDevice *s = container_of(n, USBHostDevice, exit);
1190
1191 if (s->fd != -1) {
1192 ioctl(s->fd, USBDEVFS_RESET);
1193 }
1194}
1195
26a9e82a
GH
1196static int usb_host_initfn(USBDevice *dev)
1197{
1198 USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev);
1199
1200 dev->auto_attach = 0;
1201 s->fd = -1;
1202 QTAILQ_INSERT_TAIL(&hostdevs, s, next);
b373a63a
SH
1203 s->exit.notify = usb_host_exit_notifier;
1204 qemu_add_exit_notifier(&s->exit);
26a9e82a
GH
1205 usb_host_auto_check(NULL);
1206 return 0;
a594cfbf 1207}
bb36d470 1208
806b6024 1209static struct USBDeviceInfo usb_host_dev_info = {
06384698 1210 .product_desc = "USB Host Device",
556cd098 1211 .qdev.name = "usb-host",
806b6024
GH
1212 .qdev.size = sizeof(USBHostDevice),
1213 .init = usb_host_initfn,
50b7963e 1214 .handle_packet = usb_generic_handle_packet,
eb5e680a 1215 .cancel_packet = usb_host_async_cancel,
50b7963e
HG
1216 .handle_data = usb_host_handle_data,
1217 .handle_control = usb_host_handle_control,
806b6024 1218 .handle_reset = usb_host_handle_reset,
806b6024 1219 .handle_destroy = usb_host_handle_destroy,
26a9e82a
GH
1220 .usbdevice_name = "host",
1221 .usbdevice_init = usb_host_device_open,
1222 .qdev.props = (Property[]) {
1223 DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0),
1224 DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0),
9056a297 1225 DEFINE_PROP_STRING("hostport", USBHostDevice, match.port),
26a9e82a
GH
1226 DEFINE_PROP_HEX32("vendorid", USBHostDevice, match.vendor_id, 0),
1227 DEFINE_PROP_HEX32("productid", USBHostDevice, match.product_id, 0),
1228 DEFINE_PROP_END_OF_LIST(),
1229 },
806b6024
GH
1230};
1231
1232static void usb_host_register_devices(void)
1233{
1234 usb_qdev_register(&usb_host_dev_info);
1235}
1236device_init(usb_host_register_devices)
1237
4b096fc9
AL
1238USBDevice *usb_host_device_open(const char *devname)
1239{
0745eb1e 1240 struct USBAutoFilter filter;
26a9e82a 1241 USBDevice *dev;
26a9e82a
GH
1242 char *p;
1243
556cd098 1244 dev = usb_create(NULL /* FIXME */, "usb-host");
4b096fc9 1245
5d0c5750 1246 if (strstr(devname, "auto:")) {
2791104c 1247 if (parse_filter(devname, &filter) < 0) {
26a9e82a 1248 goto fail;
2791104c 1249 }
26a9e82a
GH
1250 } else {
1251 if ((p = strchr(devname, '.'))) {
0745eb1e
MA
1252 filter.bus_num = strtoul(devname, NULL, 0);
1253 filter.addr = strtoul(p + 1, NULL, 0);
1254 filter.vendor_id = 0;
1255 filter.product_id = 0;
26a9e82a 1256 } else if ((p = strchr(devname, ':'))) {
0745eb1e
MA
1257 filter.bus_num = 0;
1258 filter.addr = 0;
26a9e82a 1259 filter.vendor_id = strtoul(devname, NULL, 16);
0745eb1e 1260 filter.product_id = strtoul(p + 1, NULL, 16);
26a9e82a
GH
1261 } else {
1262 goto fail;
1263 }
5d0c5750 1264 }
4b096fc9 1265
0745eb1e
MA
1266 qdev_prop_set_uint32(&dev->qdev, "hostbus", filter.bus_num);
1267 qdev_prop_set_uint32(&dev->qdev, "hostaddr", filter.addr);
26a9e82a
GH
1268 qdev_prop_set_uint32(&dev->qdev, "vendorid", filter.vendor_id);
1269 qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
beb6f0de 1270 qdev_init_nofail(&dev->qdev);
26a9e82a 1271 return dev;
5d0c5750 1272
26a9e82a
GH
1273fail:
1274 qdev_free(&dev->qdev);
1275 return NULL;
4b096fc9 1276}
5d0c5750
AL
1277
1278int usb_host_device_close(const char *devname)
1279{
26a9e82a 1280#if 0
5d0c5750
AL
1281 char product_name[PRODUCT_NAME_SZ];
1282 int bus_num, addr;
1283 USBHostDevice *s;
1284
2791104c 1285 if (strstr(devname, "auto:")) {
5d0c5750 1286 return usb_host_auto_del(devname);
2791104c
DA
1287 }
1288 if (usb_host_find_device(&bus_num, &addr, product_name,
1289 sizeof(product_name), devname) < 0) {
5d0c5750 1290 return -1;
2791104c 1291 }
5d0c5750
AL
1292 s = hostdev_find(bus_num, addr);
1293 if (s) {
a5d2f727 1294 usb_device_delete_addr(s->bus_num, s->dev.addr);
5d0c5750
AL
1295 return 0;
1296 }
26a9e82a 1297#endif
5d0c5750
AL
1298
1299 return -1;
1300}
a5d2f727 1301
a594cfbf 1302static int get_tag_value(char *buf, int buf_size,
5fafdf24 1303 const char *str, const char *tag,
a594cfbf
FB
1304 const char *stopchars)
1305{
1306 const char *p;
1307 char *q;
1308 p = strstr(str, tag);
2791104c 1309 if (!p) {
a594cfbf 1310 return -1;
2791104c 1311 }
a594cfbf 1312 p += strlen(tag);
2791104c 1313 while (qemu_isspace(*p)) {
a594cfbf 1314 p++;
2791104c 1315 }
a594cfbf
FB
1316 q = buf;
1317 while (*p != '\0' && !strchr(stopchars, *p)) {
2791104c 1318 if ((q - buf) < (buf_size - 1)) {
a594cfbf 1319 *q++ = *p;
2791104c 1320 }
a594cfbf
FB
1321 p++;
1322 }
1323 *q = '\0';
1324 return q - buf;
bb36d470
FB
1325}
1326
0f431527
AL
1327/*
1328 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1329 * host's USB devices. This is legacy support since many distributions
1330 * are moving to /sys/bus/usb
1331 */
1332static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
bb36d470 1333{
660f11be 1334 FILE *f = NULL;
a594cfbf 1335 char line[1024];
bb36d470 1336 char buf[1024];
a594cfbf 1337 int bus_num, addr, speed, device_count, class_id, product_id, vendor_id;
a594cfbf 1338 char product_name[512];
0f431527 1339 int ret = 0;
3b46e624 1340
0f431527
AL
1341 if (!usb_host_device_path) {
1342 perror("husb: USB Host Device Path not set");
1343 goto the_end;
1344 }
1345 snprintf(line, sizeof(line), "%s/devices", usb_host_device_path);
1346 f = fopen(line, "r");
a594cfbf 1347 if (!f) {
0f431527
AL
1348 perror("husb: cannot open devices file");
1349 goto the_end;
a594cfbf 1350 }
0f431527 1351
a594cfbf 1352 device_count = 0;
3991c35e
HG
1353 bus_num = addr = class_id = product_id = vendor_id = 0;
1354 speed = -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
bb36d470 1355 for(;;) {
2791104c 1356 if (fgets(line, sizeof(line), f) == NULL) {
bb36d470 1357 break;
2791104c
DA
1358 }
1359 if (strlen(line) > 0) {
a594cfbf 1360 line[strlen(line) - 1] = '\0';
2791104c 1361 }
a594cfbf 1362 if (line[0] == 'T' && line[1] == ':') {
38ca0f6d
PB
1363 if (device_count && (vendor_id || product_id)) {
1364 /* New device. Add the previously discovered device. */
0f5160d1 1365 ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
a594cfbf 1366 product_id, product_name, speed);
2791104c 1367 if (ret) {
a594cfbf 1368 goto the_end;
2791104c 1369 }
a594cfbf 1370 }
2791104c 1371 if (get_tag_value(buf, sizeof(buf), line, "Bus=", " ") < 0) {
a594cfbf 1372 goto fail;
2791104c 1373 }
a594cfbf 1374 bus_num = atoi(buf);
2791104c 1375 if (get_tag_value(buf, sizeof(buf), line, "Dev#=", " ") < 0) {
a594cfbf 1376 goto fail;
2791104c 1377 }
a594cfbf 1378 addr = atoi(buf);
2791104c 1379 if (get_tag_value(buf, sizeof(buf), line, "Spd=", " ") < 0) {
a594cfbf 1380 goto fail;
2791104c 1381 }
f264cfbf
HG
1382 if (!strcmp(buf, "5000")) {
1383 speed = USB_SPEED_SUPER;
1384 } else if (!strcmp(buf, "480")) {
a594cfbf 1385 speed = USB_SPEED_HIGH;
2791104c 1386 } else if (!strcmp(buf, "1.5")) {
a594cfbf 1387 speed = USB_SPEED_LOW;
2791104c 1388 } else {
a594cfbf 1389 speed = USB_SPEED_FULL;
2791104c 1390 }
a594cfbf
FB
1391 product_name[0] = '\0';
1392 class_id = 0xff;
1393 device_count++;
1394 product_id = 0;
1395 vendor_id = 0;
1396 } else if (line[0] == 'P' && line[1] == ':') {
2791104c 1397 if (get_tag_value(buf, sizeof(buf), line, "Vendor=", " ") < 0) {
a594cfbf 1398 goto fail;
2791104c 1399 }
a594cfbf 1400 vendor_id = strtoul(buf, NULL, 16);
2791104c 1401 if (get_tag_value(buf, sizeof(buf), line, "ProdID=", " ") < 0) {
a594cfbf 1402 goto fail;
2791104c 1403 }
a594cfbf
FB
1404 product_id = strtoul(buf, NULL, 16);
1405 } else if (line[0] == 'S' && line[1] == ':') {
2791104c 1406 if (get_tag_value(buf, sizeof(buf), line, "Product=", "") < 0) {
a594cfbf 1407 goto fail;
2791104c 1408 }
a594cfbf
FB
1409 pstrcpy(product_name, sizeof(product_name), buf);
1410 } else if (line[0] == 'D' && line[1] == ':') {
2791104c 1411 if (get_tag_value(buf, sizeof(buf), line, "Cls=", " (") < 0) {
a594cfbf 1412 goto fail;
2791104c 1413 }
a594cfbf 1414 class_id = strtoul(buf, NULL, 16);
bb36d470 1415 }
a594cfbf
FB
1416 fail: ;
1417 }
38ca0f6d
PB
1418 if (device_count && (vendor_id || product_id)) {
1419 /* Add the last device. */
0f5160d1 1420 ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
a594cfbf 1421 product_id, product_name, speed);
bb36d470 1422 }
a594cfbf 1423 the_end:
2791104c 1424 if (f) {
0f431527 1425 fclose(f);
2791104c 1426 }
0f431527
AL
1427 return ret;
1428}
1429
1430/*
1431 * Read sys file-system device file
1432 *
1433 * @line address of buffer to put file contents in
1434 * @line_size size of line
1435 * @device_file path to device file (printf format string)
1436 * @device_name device being opened (inserted into device_file)
1437 *
1438 * @return 0 failed, 1 succeeded ('line' contains data)
1439 */
2791104c
DA
1440static int usb_host_read_file(char *line, size_t line_size,
1441 const char *device_file, const char *device_name)
0f431527
AL
1442{
1443 FILE *f;
1444 int ret = 0;
1445 char filename[PATH_MAX];
1446
b4e237aa
BS
1447 snprintf(filename, PATH_MAX, USBSYSBUS_PATH "/devices/%s/%s", device_name,
1448 device_file);
0f431527
AL
1449 f = fopen(filename, "r");
1450 if (f) {
9f99cee7 1451 ret = fgets(line, line_size, f) != NULL;
0f431527 1452 fclose(f);
0f431527
AL
1453 }
1454
1455 return ret;
1456}
1457
1458/*
1459 * Use /sys/bus/usb/devices/ directory to determine host's USB
1460 * devices.
1461 *
1462 * This code is based on Robert Schiele's original patches posted to
1463 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1464 */
1465static int usb_host_scan_sys(void *opaque, USBScanFunc *func)
1466{
660f11be 1467 DIR *dir = NULL;
0f431527 1468 char line[1024];
5557d820 1469 int bus_num, addr, speed, class_id, product_id, vendor_id;
0f431527 1470 int ret = 0;
5557d820 1471 char port[MAX_PORTLEN];
0f431527
AL
1472 char product_name[512];
1473 struct dirent *de;
1474
1475 dir = opendir(USBSYSBUS_PATH "/devices");
1476 if (!dir) {
1477 perror("husb: cannot open devices directory");
1478 goto the_end;
1479 }
1480
1481 while ((de = readdir(dir))) {
1482 if (de->d_name[0] != '.' && !strchr(de->d_name, ':')) {
5557d820
GH
1483 if (sscanf(de->d_name, "%d-%7[0-9.]", &bus_num, port) < 2) {
1484 continue;
0f5160d1 1485 }
0f431527 1486
2791104c 1487 if (!usb_host_read_file(line, sizeof(line), "devnum", de->d_name)) {
0f431527 1488 goto the_end;
2791104c
DA
1489 }
1490 if (sscanf(line, "%d", &addr) != 1) {
0f431527 1491 goto the_end;
2791104c 1492 }
b4e237aa 1493 if (!usb_host_read_file(line, sizeof(line), "bDeviceClass",
2791104c 1494 de->d_name)) {
0f431527 1495 goto the_end;
2791104c
DA
1496 }
1497 if (sscanf(line, "%x", &class_id) != 1) {
0f431527 1498 goto the_end;
2791104c 1499 }
0f431527 1500
2791104c
DA
1501 if (!usb_host_read_file(line, sizeof(line), "idVendor",
1502 de->d_name)) {
0f431527 1503 goto the_end;
2791104c
DA
1504 }
1505 if (sscanf(line, "%x", &vendor_id) != 1) {
0f431527 1506 goto the_end;
2791104c 1507 }
b4e237aa 1508 if (!usb_host_read_file(line, sizeof(line), "idProduct",
2791104c 1509 de->d_name)) {
0f431527 1510 goto the_end;
2791104c
DA
1511 }
1512 if (sscanf(line, "%x", &product_id) != 1) {
0f431527 1513 goto the_end;
2791104c 1514 }
b4e237aa
BS
1515 if (!usb_host_read_file(line, sizeof(line), "product",
1516 de->d_name)) {
0f431527
AL
1517 *product_name = 0;
1518 } else {
2791104c 1519 if (strlen(line) > 0) {
0f431527 1520 line[strlen(line) - 1] = '\0';
2791104c 1521 }
0f431527
AL
1522 pstrcpy(product_name, sizeof(product_name), line);
1523 }
1524
2791104c 1525 if (!usb_host_read_file(line, sizeof(line), "speed", de->d_name)) {
0f431527 1526 goto the_end;
2791104c 1527 }
f264cfbf
HG
1528 if (!strcmp(line, "5000\n")) {
1529 speed = USB_SPEED_SUPER;
1530 } else if (!strcmp(line, "480\n")) {
0f431527 1531 speed = USB_SPEED_HIGH;
2791104c 1532 } else if (!strcmp(line, "1.5\n")) {
0f431527 1533 speed = USB_SPEED_LOW;
2791104c 1534 } else {
0f431527 1535 speed = USB_SPEED_FULL;
2791104c 1536 }
0f431527 1537
5557d820 1538 ret = func(opaque, bus_num, addr, port, class_id, vendor_id,
0f431527 1539 product_id, product_name, speed);
2791104c 1540 if (ret) {
0f431527 1541 goto the_end;
2791104c 1542 }
0f431527
AL
1543 }
1544 }
1545 the_end:
2791104c 1546 if (dir) {
0f431527 1547 closedir(dir);
2791104c 1548 }
0f431527
AL
1549 return ret;
1550}
1551
1552/*
1553 * Determine how to access the host's USB devices and call the
1554 * specific support function.
1555 */
1556static int usb_host_scan(void *opaque, USBScanFunc *func)
1557{
376253ec 1558 Monitor *mon = cur_mon;
660f11be
BS
1559 FILE *f = NULL;
1560 DIR *dir = NULL;
0f431527 1561 int ret = 0;
0f431527
AL
1562 const char *fs_type[] = {"unknown", "proc", "dev", "sys"};
1563 char devpath[PATH_MAX];
1564
1565 /* only check the host once */
1566 if (!usb_fs_type) {
55496240
MM
1567 dir = opendir(USBSYSBUS_PATH "/devices");
1568 if (dir) {
1569 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1570 strcpy(devpath, USBDEVBUS_PATH);
1571 usb_fs_type = USB_FS_SYS;
1572 closedir(dir);
d0f2c4c6 1573 DPRINTF(USBDBG_DEVOPENED, USBSYSBUS_PATH);
55496240
MM
1574 goto found_devices;
1575 }
0f431527
AL
1576 f = fopen(USBPROCBUS_PATH "/devices", "r");
1577 if (f) {
1578 /* devices found in /proc/bus/usb/ */
1579 strcpy(devpath, USBPROCBUS_PATH);
1580 usb_fs_type = USB_FS_PROC;
1581 fclose(f);
d0f2c4c6 1582 DPRINTF(USBDBG_DEVOPENED, USBPROCBUS_PATH);
f16a0db3 1583 goto found_devices;
0f431527
AL
1584 }
1585 /* try additional methods if an access method hasn't been found yet */
1586 f = fopen(USBDEVBUS_PATH "/devices", "r");
f16a0db3 1587 if (f) {
0f431527
AL
1588 /* devices found in /dev/bus/usb/ */
1589 strcpy(devpath, USBDEVBUS_PATH);
1590 usb_fs_type = USB_FS_DEV;
1591 fclose(f);
d0f2c4c6 1592 DPRINTF(USBDBG_DEVOPENED, USBDEVBUS_PATH);
f16a0db3 1593 goto found_devices;
0f431527 1594 }
f16a0db3 1595 found_devices:
22babebb 1596 if (!usb_fs_type) {
2791104c 1597 if (mon) {
eba6fe87 1598 monitor_printf(mon, "husb: unable to access USB devices\n");
2791104c 1599 }
f16a0db3 1600 return -ENOENT;
0f431527
AL
1601 }
1602
1603 /* the module setting (used later for opening devices) */
1604 usb_host_device_path = qemu_mallocz(strlen(devpath)+1);
1eec614b 1605 strcpy(usb_host_device_path, devpath);
2791104c 1606 if (mon) {
eba6fe87
GH
1607 monitor_printf(mon, "husb: using %s file-system with %s\n",
1608 fs_type[usb_fs_type], usb_host_device_path);
2791104c 1609 }
0f431527
AL
1610 }
1611
1612 switch (usb_fs_type) {
1613 case USB_FS_PROC:
1614 case USB_FS_DEV:
1615 ret = usb_host_scan_dev(opaque, func);
1616 break;
1617 case USB_FS_SYS:
1618 ret = usb_host_scan_sys(opaque, func);
1619 break;
f16a0db3
AL
1620 default:
1621 ret = -EINVAL;
1622 break;
0f431527 1623 }
a594cfbf 1624 return ret;
bb36d470
FB
1625}
1626
4b096fc9 1627static QEMUTimer *usb_auto_timer;
4b096fc9 1628
5557d820 1629static int usb_host_auto_scan(void *opaque, int bus_num, int addr, char *port,
26a9e82a
GH
1630 int class_id, int vendor_id, int product_id,
1631 const char *product_name, int speed)
4b096fc9
AL
1632{
1633 struct USBAutoFilter *f;
26a9e82a 1634 struct USBHostDevice *s;
4b096fc9
AL
1635
1636 /* Ignore hubs */
1637 if (class_id == 9)
1638 return 0;
1639
26a9e82a
GH
1640 QTAILQ_FOREACH(s, &hostdevs, next) {
1641 f = &s->match;
1642
2791104c 1643 if (f->bus_num > 0 && f->bus_num != bus_num) {
4b096fc9 1644 continue;
2791104c
DA
1645 }
1646 if (f->addr > 0 && f->addr != addr) {
4b096fc9 1647 continue;
2791104c 1648 }
9056a297
GH
1649 if (f->port != NULL && (port == NULL || strcmp(f->port, port) != 0)) {
1650 continue;
1651 }
4b096fc9 1652
2791104c 1653 if (f->vendor_id > 0 && f->vendor_id != vendor_id) {
4b096fc9 1654 continue;
2791104c 1655 }
4b096fc9 1656
2791104c 1657 if (f->product_id > 0 && f->product_id != product_id) {
4b096fc9 1658 continue;
2791104c 1659 }
4b096fc9
AL
1660 /* We got a match */
1661
33e66b86 1662 /* Already attached ? */
2791104c 1663 if (s->fd != -1) {
4b096fc9 1664 return 0;
2791104c 1665 }
d0f2c4c6 1666 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num, addr);
4b096fc9 1667
3991c35e 1668 usb_host_open(s, bus_num, addr, port, product_name, speed);
4b096fc9
AL
1669 }
1670
1671 return 0;
1672}
1673
26a9e82a 1674static void usb_host_auto_check(void *unused)
4b096fc9 1675{
26a9e82a
GH
1676 struct USBHostDevice *s;
1677 int unconnected = 0;
1678
4b096fc9 1679 usb_host_scan(NULL, usb_host_auto_scan);
26a9e82a
GH
1680
1681 QTAILQ_FOREACH(s, &hostdevs, next) {
2791104c 1682 if (s->fd == -1) {
26a9e82a 1683 unconnected++;
2791104c 1684 }
26a9e82a
GH
1685 }
1686
1687 if (unconnected == 0) {
1688 /* nothing to watch */
2791104c 1689 if (usb_auto_timer) {
26a9e82a 1690 qemu_del_timer(usb_auto_timer);
2791104c 1691 }
26a9e82a
GH
1692 return;
1693 }
1694
1695 if (!usb_auto_timer) {
7bd427d8 1696 usb_auto_timer = qemu_new_timer_ms(rt_clock, usb_host_auto_check, NULL);
2791104c 1697 if (!usb_auto_timer) {
26a9e82a 1698 return;
2791104c 1699 }
26a9e82a 1700 }
7bd427d8 1701 qemu_mod_timer(usb_auto_timer, qemu_get_clock_ms(rt_clock) + 2000);
4b096fc9
AL
1702}
1703
1704/*
5d0c5750
AL
1705 * Autoconnect filter
1706 * Format:
1707 * auto:bus:dev[:vid:pid]
1708 * auto:bus.dev[:vid:pid]
1709 *
1710 * bus - bus number (dec, * means any)
1711 * dev - device number (dec, * means any)
1712 * vid - vendor id (hex, * means any)
1713 * pid - product id (hex, * means any)
1714 *
1715 * See 'lsusb' output.
4b096fc9 1716 */
5d0c5750 1717static int parse_filter(const char *spec, struct USBAutoFilter *f)
4b096fc9 1718{
5d0c5750
AL
1719 enum { BUS, DEV, VID, PID, DONE };
1720 const char *p = spec;
1721 int i;
1722
0745eb1e
MA
1723 f->bus_num = 0;
1724 f->addr = 0;
1725 f->vendor_id = 0;
1726 f->product_id = 0;
5d0c5750
AL
1727
1728 for (i = BUS; i < DONE; i++) {
2791104c
DA
1729 p = strpbrk(p, ":.");
1730 if (!p) {
1731 break;
1732 }
5d0c5750 1733 p++;
5d0c5750 1734
2791104c
DA
1735 if (*p == '*') {
1736 continue;
1737 }
5d0c5750
AL
1738 switch(i) {
1739 case BUS: f->bus_num = strtol(p, NULL, 10); break;
1740 case DEV: f->addr = strtol(p, NULL, 10); break;
1741 case VID: f->vendor_id = strtol(p, NULL, 16); break;
1742 case PID: f->product_id = strtol(p, NULL, 16); break;
1743 }
1744 }
1745
1746 if (i < DEV) {
1747 fprintf(stderr, "husb: invalid auto filter spec %s\n", spec);
1748 return -1;
1749 }
1750
1751 return 0;
1752}
1753
a594cfbf
FB
1754/**********************/
1755/* USB host device info */
1756
1757struct usb_class_info {
1758 int class;
1759 const char *class_name;
1760};
1761
1762static const struct usb_class_info usb_class_info[] = {
1763 { USB_CLASS_AUDIO, "Audio"},
1764 { USB_CLASS_COMM, "Communication"},
1765 { USB_CLASS_HID, "HID"},
1766 { USB_CLASS_HUB, "Hub" },
1767 { USB_CLASS_PHYSICAL, "Physical" },
1768 { USB_CLASS_PRINTER, "Printer" },
1769 { USB_CLASS_MASS_STORAGE, "Storage" },
1770 { USB_CLASS_CDC_DATA, "Data" },
1771 { USB_CLASS_APP_SPEC, "Application Specific" },
1772 { USB_CLASS_VENDOR_SPEC, "Vendor Specific" },
1773 { USB_CLASS_STILL_IMAGE, "Still Image" },
b9dc033c 1774 { USB_CLASS_CSCID, "Smart Card" },
a594cfbf
FB
1775 { USB_CLASS_CONTENT_SEC, "Content Security" },
1776 { -1, NULL }
1777};
1778
1779static const char *usb_class_str(uint8_t class)
bb36d470 1780{
a594cfbf
FB
1781 const struct usb_class_info *p;
1782 for(p = usb_class_info; p->class != -1; p++) {
2791104c 1783 if (p->class == class) {
a594cfbf 1784 break;
2791104c 1785 }
bb36d470 1786 }
a594cfbf
FB
1787 return p->class_name;
1788}
1789
5557d820
GH
1790static void usb_info_device(Monitor *mon, int bus_num, int addr, char *port,
1791 int class_id, int vendor_id, int product_id,
9596ebb7
PB
1792 const char *product_name,
1793 int speed)
a594cfbf
FB
1794{
1795 const char *class_str, *speed_str;
1796
1797 switch(speed) {
5fafdf24
TS
1798 case USB_SPEED_LOW:
1799 speed_str = "1.5";
a594cfbf 1800 break;
5fafdf24
TS
1801 case USB_SPEED_FULL:
1802 speed_str = "12";
a594cfbf 1803 break;
5fafdf24
TS
1804 case USB_SPEED_HIGH:
1805 speed_str = "480";
a594cfbf 1806 break;
f264cfbf
HG
1807 case USB_SPEED_SUPER:
1808 speed_str = "5000";
1809 break;
a594cfbf 1810 default:
5fafdf24 1811 speed_str = "?";
a594cfbf
FB
1812 break;
1813 }
1814
5557d820
GH
1815 monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1816 bus_num, addr, port, speed_str);
a594cfbf 1817 class_str = usb_class_str(class_id);
2791104c 1818 if (class_str) {
376253ec 1819 monitor_printf(mon, " %s:", class_str);
2791104c 1820 } else {
376253ec 1821 monitor_printf(mon, " Class %02x:", class_id);
2791104c 1822 }
376253ec 1823 monitor_printf(mon, " USB device %04x:%04x", vendor_id, product_id);
2791104c 1824 if (product_name[0] != '\0') {
376253ec 1825 monitor_printf(mon, ", %s", product_name);
2791104c 1826 }
376253ec 1827 monitor_printf(mon, "\n");
a594cfbf
FB
1828}
1829
5fafdf24 1830static int usb_host_info_device(void *opaque, int bus_num, int addr,
5557d820 1831 char *path, int class_id,
5fafdf24 1832 int vendor_id, int product_id,
a594cfbf
FB
1833 const char *product_name,
1834 int speed)
1835{
179da8af
BS
1836 Monitor *mon = opaque;
1837
5557d820 1838 usb_info_device(mon, bus_num, addr, path, class_id, vendor_id, product_id,
a594cfbf
FB
1839 product_name, speed);
1840 return 0;
1841}
1842
ac4ffb5a 1843static void dec2str(int val, char *str, size_t size)
5d0c5750 1844{
2791104c 1845 if (val == 0) {
ac4ffb5a 1846 snprintf(str, size, "*");
2791104c
DA
1847 } else {
1848 snprintf(str, size, "%d", val);
1849 }
5d0c5750
AL
1850}
1851
ac4ffb5a 1852static void hex2str(int val, char *str, size_t size)
5d0c5750 1853{
2791104c 1854 if (val == 0) {
ac4ffb5a 1855 snprintf(str, size, "*");
2791104c 1856 } else {
26a9e82a 1857 snprintf(str, size, "%04x", val);
2791104c 1858 }
5d0c5750
AL
1859}
1860
376253ec 1861void usb_host_info(Monitor *mon)
a594cfbf 1862{
5d0c5750 1863 struct USBAutoFilter *f;
26a9e82a 1864 struct USBHostDevice *s;
5d0c5750 1865
179da8af 1866 usb_host_scan(mon, usb_host_info_device);
5d0c5750 1867
2791104c 1868 if (QTAILQ_EMPTY(&hostdevs)) {
26a9e82a 1869 return;
2791104c
DA
1870 }
1871
26a9e82a
GH
1872 monitor_printf(mon, " Auto filters:\n");
1873 QTAILQ_FOREACH(s, &hostdevs, next) {
5d0c5750 1874 char bus[10], addr[10], vid[10], pid[10];
26a9e82a 1875 f = &s->match;
ac4ffb5a
AL
1876 dec2str(f->bus_num, bus, sizeof(bus));
1877 dec2str(f->addr, addr, sizeof(addr));
1878 hex2str(f->vendor_id, vid, sizeof(vid));
1879 hex2str(f->product_id, pid, sizeof(pid));
9056a297
GH
1880 monitor_printf(mon, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1881 bus, addr, f->port ? f->port : "*", vid, pid);
5d0c5750 1882 }
bb36d470 1883}