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