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