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