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