2 * Linux host USB redirector
4 * Copyright (c) 2005 Fabrice Bellard
6 * Copyright (c) 2008 Max Krasnyansky
7 * Support for host device auto connect & disconnect
8 * Major rewrite to support fully async operation
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
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:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
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
33 #include "qemu-common.h"
34 #include "qemu-timer.h"
39 #include <sys/ioctl.h>
41 #include <linux/usbdevice_fs.h>
42 #include <linux/version.h>
45 /* We redefine it to avoid version problems */
46 struct usb_ctrltransfer
{
56 typedef int USBScanFunc(void *opaque
, int bus_num
, int addr
, char *port
,
57 int class_id
, int vendor_id
, int product_id
,
58 const char *product_name
, int speed
);
63 #define DPRINTF printf
68 #define USBDBG_DEVOPENED "husb: opened %s/devices\n"
70 #define USBPROCBUS_PATH "/proc/bus/usb"
71 #define PRODUCT_NAME_SZ 32
72 #define MAX_ENDPOINTS 15
73 #define MAX_PORTLEN 16
74 #define USBDEVBUS_PATH "/dev/bus/usb"
75 #define USBSYSBUS_PATH "/sys/bus/usb"
77 static char *usb_host_device_path
;
84 static int usb_fs_type
;
86 /* endpoint association data */
87 #define ISO_FRAME_DESC_PER_URB 32
88 #define ISO_URB_COUNT 3
89 #define INVALID_EP_TYPE 255
91 /* devio.c limits single requests to 16k */
92 #define MAX_USBFS_BUFFER_SIZE 16384
94 typedef struct AsyncURB AsyncURB
;
106 struct USBAutoFilter
{
114 typedef struct USBHostDevice
{
125 struct endp_data endp_table
[MAX_ENDPOINTS
];
126 QLIST_HEAD(, AsyncURB
) aurbs
;
128 /* Host side address */
131 char port
[MAX_PORTLEN
];
132 struct USBAutoFilter match
;
134 QTAILQ_ENTRY(USBHostDevice
) next
;
137 static QTAILQ_HEAD(, USBHostDevice
) hostdevs
= QTAILQ_HEAD_INITIALIZER(hostdevs
);
139 static int usb_host_close(USBHostDevice
*dev
);
140 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
);
141 static void usb_host_auto_check(void *unused
);
142 static int usb_host_read_file(char *line
, size_t line_size
,
143 const char *device_file
, const char *device_name
);
145 static int is_isoc(USBHostDevice
*s
, int ep
)
147 return s
->endp_table
[ep
- 1].type
== USBDEVFS_URB_TYPE_ISO
;
150 static int is_valid(USBHostDevice
*s
, int ep
)
152 return s
->endp_table
[ep
- 1].type
!= INVALID_EP_TYPE
;
155 static int is_halted(USBHostDevice
*s
, int ep
)
157 return s
->endp_table
[ep
- 1].halted
;
160 static void clear_halt(USBHostDevice
*s
, int ep
)
162 s
->endp_table
[ep
- 1].halted
= 0;
165 static void set_halt(USBHostDevice
*s
, int ep
)
167 s
->endp_table
[ep
- 1].halted
= 1;
170 static int is_iso_started(USBHostDevice
*s
, int ep
)
172 return s
->endp_table
[ep
- 1].iso_started
;
175 static void clear_iso_started(USBHostDevice
*s
, int ep
)
177 s
->endp_table
[ep
- 1].iso_started
= 0;
180 static void set_iso_started(USBHostDevice
*s
, int ep
)
182 s
->endp_table
[ep
- 1].iso_started
= 1;
185 static void set_iso_urb(USBHostDevice
*s
, int ep
, AsyncURB
*iso_urb
)
187 s
->endp_table
[ep
- 1].iso_urb
= iso_urb
;
190 static AsyncURB
*get_iso_urb(USBHostDevice
*s
, int ep
)
192 return s
->endp_table
[ep
- 1].iso_urb
;
195 static void set_iso_urb_idx(USBHostDevice
*s
, int ep
, int i
)
197 s
->endp_table
[ep
- 1].iso_urb_idx
= i
;
200 static int get_iso_urb_idx(USBHostDevice
*s
, int ep
)
202 return s
->endp_table
[ep
- 1].iso_urb_idx
;
205 static void set_iso_buffer_used(USBHostDevice
*s
, int ep
, int i
)
207 s
->endp_table
[ep
- 1].iso_buffer_used
= i
;
210 static int get_iso_buffer_used(USBHostDevice
*s
, int ep
)
212 return s
->endp_table
[ep
- 1].iso_buffer_used
;
215 static void set_max_packet_size(USBHostDevice
*s
, int ep
, uint8_t *descriptor
)
217 int raw
= descriptor
[4] + (descriptor
[5] << 8);
218 int size
, microframes
;
221 switch ((raw
>> 11) & 3) {
222 case 1: microframes
= 2; break;
223 case 2: microframes
= 3; break;
224 default: microframes
= 1; break;
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
;
231 static int get_max_packet_size(USBHostDevice
*s
, int ep
)
233 return s
->endp_table
[ep
- 1].max_packet_size
;
238 * We always allocate iso packet descriptors even for bulk transfers
239 * to simplify allocation and casts.
243 struct usbdevfs_urb urb
;
244 struct usbdevfs_iso_packet_desc isocpd
[ISO_FRAME_DESC_PER_URB
];
246 QLIST_ENTRY(AsyncURB
) next
;
248 /* For regular async urbs */
250 int more
; /* large transfer, more urbs follow */
252 /* For buffered iso handling */
253 int iso_frame_idx
; /* -1 means in flight */
256 static AsyncURB
*async_alloc(USBHostDevice
*s
)
258 AsyncURB
*aurb
= qemu_mallocz(sizeof(AsyncURB
));
260 QLIST_INSERT_HEAD(&s
->aurbs
, aurb
, next
);
264 static void async_free(AsyncURB
*aurb
)
266 QLIST_REMOVE(aurb
, next
);
270 static void do_disconnect(USBHostDevice
*s
)
272 printf("husb: device %d.%d disconnected\n",
273 s
->bus_num
, s
->addr
);
275 usb_host_auto_check(NULL
);
278 static void async_complete(void *opaque
)
280 USBHostDevice
*s
= opaque
;
286 int r
= ioctl(s
->fd
, USBDEVFS_REAPURBNDELAY
, &aurb
);
288 if (errno
== EAGAIN
) {
291 if (errno
== ENODEV
&& !s
->closing
) {
296 DPRINTF("husb: async. reap urb failed errno %d\n", errno
);
300 DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
301 aurb
, aurb
->urb
.status
, aurb
->urb
.actual_length
);
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);
309 aurb
->iso_frame_idx
= 0;
316 switch (aurb
->urb
.status
) {
318 p
->len
+= aurb
->urb
.actual_length
;
322 set_halt(s
, p
->devep
);
323 p
->len
= USB_RET_STALL
;
327 p
->len
= USB_RET_NAK
;
331 if (aurb
->urb
.type
== USBDEVFS_URB_TYPE_CONTROL
) {
332 usb_generic_async_ctrl_complete(&s
->dev
, p
);
333 } else if (!aurb
->more
) {
334 usb_packet_complete(&s
->dev
, p
);
342 static void usb_host_async_cancel(USBDevice
*dev
, USBPacket
*p
)
344 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
347 QLIST_FOREACH(aurb
, &s
->aurbs
, next
) {
348 if (p
!= aurb
->packet
) {
352 DPRINTF("husb: async cancel: packet %p, aurb %p\n", p
, aurb
);
354 /* Mark it as dead (see async_complete above) */
357 int r
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, aurb
);
359 DPRINTF("husb: async. discard urb failed errno %d\n", errno
);
364 static int usb_host_claim_interfaces(USBHostDevice
*dev
, int configuration
)
366 const char *op
= NULL
;
367 int dev_descr_len
, config_descr_len
;
368 int interface
, nb_interfaces
;
371 if (configuration
== 0) /* address state - ignore */
374 DPRINTF("husb: claiming interfaces. config %d\n", configuration
);
377 dev_descr_len
= dev
->descr
[0];
378 if (dev_descr_len
> dev
->descr_len
) {
379 fprintf(stderr
, "husb: update iface failed. descr too short\n");
384 while (i
< dev
->descr_len
) {
385 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
387 dev
->descr
[i
], dev
->descr
[i
+1]);
389 if (dev
->descr
[i
+1] != USB_DT_CONFIG
) {
393 config_descr_len
= dev
->descr
[i
];
395 printf("husb: config #%d need %d\n", dev
->descr
[i
+ 5], configuration
);
397 if (configuration
< 0 || configuration
== dev
->descr
[i
+ 5]) {
398 configuration
= dev
->descr
[i
+ 5];
402 i
+= config_descr_len
;
405 if (i
>= dev
->descr_len
) {
407 "husb: update iface failed. no matching configuration\n");
410 nb_interfaces
= dev
->descr
[i
+ 4];
412 #ifdef USBDEVFS_DISCONNECT
413 /* earlier Linux 2.4 do not support that */
415 struct usbdevfs_ioctl ctrl
;
416 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
417 ctrl
.ioctl_code
= USBDEVFS_DISCONNECT
;
418 ctrl
.ifno
= interface
;
420 op
= "USBDEVFS_DISCONNECT";
421 ret
= ioctl(dev
->fd
, USBDEVFS_IOCTL
, &ctrl
);
422 if (ret
< 0 && errno
!= ENODATA
) {
429 /* XXX: only grab if all interfaces are free */
430 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
431 op
= "USBDEVFS_CLAIMINTERFACE";
432 ret
= ioctl(dev
->fd
, USBDEVFS_CLAIMINTERFACE
, &interface
);
434 if (errno
== EBUSY
) {
435 printf("husb: update iface. device already grabbed\n");
437 perror("husb: failed to claim interface");
443 printf("husb: %d interfaces claimed for configuration %d\n",
444 nb_interfaces
, configuration
);
446 dev
->ninterfaces
= nb_interfaces
;
447 dev
->configuration
= configuration
;
451 if (errno
== ENODEV
) {
458 static int usb_host_release_interfaces(USBHostDevice
*s
)
462 DPRINTF("husb: releasing interfaces\n");
464 for (i
= 0; i
< s
->ninterfaces
; i
++) {
465 ret
= ioctl(s
->fd
, USBDEVFS_RELEASEINTERFACE
, &i
);
467 perror("husb: failed to release interface");
475 static void usb_host_handle_reset(USBDevice
*dev
)
477 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
479 DPRINTF("husb: reset device %u.%u\n", s
->bus_num
, s
->addr
);
481 ioctl(s
->fd
, USBDEVFS_RESET
);
483 usb_host_claim_interfaces(s
, s
->configuration
);
486 static void usb_host_handle_destroy(USBDevice
*dev
)
488 USBHostDevice
*s
= (USBHostDevice
*)dev
;
491 QTAILQ_REMOVE(&hostdevs
, s
, next
);
492 qemu_remove_exit_notifier(&s
->exit
);
495 static int usb_linux_update_endp_table(USBHostDevice
*s
);
497 /* iso data is special, we need to keep enough urbs in flight to make sure
498 that the controller never runs out of them, otherwise the device will
499 likely suffer a buffer underrun / overrun. */
500 static AsyncURB
*usb_host_alloc_iso(USBHostDevice
*s
, uint8_t ep
, int in
)
503 int i
, j
, len
= get_max_packet_size(s
, ep
);
505 aurb
= qemu_mallocz(ISO_URB_COUNT
* sizeof(*aurb
));
506 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
507 aurb
[i
].urb
.endpoint
= ep
;
508 aurb
[i
].urb
.buffer_length
= ISO_FRAME_DESC_PER_URB
* len
;
509 aurb
[i
].urb
.buffer
= qemu_malloc(aurb
[i
].urb
.buffer_length
);
510 aurb
[i
].urb
.type
= USBDEVFS_URB_TYPE_ISO
;
511 aurb
[i
].urb
.flags
= USBDEVFS_URB_ISO_ASAP
;
512 aurb
[i
].urb
.number_of_packets
= ISO_FRAME_DESC_PER_URB
;
513 for (j
= 0 ; j
< ISO_FRAME_DESC_PER_URB
; j
++)
514 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
516 aurb
[i
].urb
.endpoint
|= 0x80;
517 /* Mark as fully consumed (idle) */
518 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
;
521 set_iso_urb(s
, ep
, aurb
);
526 static void usb_host_stop_n_free_iso(USBHostDevice
*s
, uint8_t ep
)
529 int i
, ret
, killed
= 0, free
= 1;
531 aurb
= get_iso_urb(s
, ep
);
536 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
538 if (aurb
[i
].iso_frame_idx
== -1) {
539 ret
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, &aurb
[i
]);
541 printf("husb: discard isoc in urb failed errno %d\n", errno
);
549 /* Make sure any urbs we've killed are reaped before we free them */
554 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
555 qemu_free(aurb
[i
].urb
.buffer
);
561 printf("husb: leaking iso urbs because of discard failure\n");
562 set_iso_urb(s
, ep
, NULL
);
563 set_iso_urb_idx(s
, ep
, 0);
564 clear_iso_started(s
, ep
);
567 static int urb_status_to_usb_ret(int status
)
571 return USB_RET_STALL
;
577 static int usb_host_handle_iso_data(USBHostDevice
*s
, USBPacket
*p
, int in
)
580 int i
, j
, ret
, max_packet_size
, offset
, len
= 0;
582 max_packet_size
= get_max_packet_size(s
, p
->devep
);
583 if (max_packet_size
== 0)
586 aurb
= get_iso_urb(s
, p
->devep
);
588 aurb
= usb_host_alloc_iso(s
, p
->devep
, in
);
591 i
= get_iso_urb_idx(s
, p
->devep
);
592 j
= aurb
[i
].iso_frame_idx
;
593 if (j
>= 0 && j
< ISO_FRAME_DESC_PER_URB
) {
595 /* Check urb status */
596 if (aurb
[i
].urb
.status
) {
597 len
= urb_status_to_usb_ret(aurb
[i
].urb
.status
);
598 /* Move to the next urb */
599 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
- 1;
600 /* Check frame status */
601 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].status
) {
602 len
= urb_status_to_usb_ret(
603 aurb
[i
].urb
.iso_frame_desc
[j
].status
);
604 /* Check the frame fits */
605 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
> p
->len
) {
606 printf("husb: received iso data is larger then packet\n");
608 /* All good copy data over */
610 len
= aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
;
613 j
* aurb
[i
].urb
.iso_frame_desc
[0].length
,
618 offset
= (j
== 0) ? 0 : get_iso_buffer_used(s
, p
->devep
);
620 /* Check the frame fits */
621 if (len
> max_packet_size
) {
622 printf("husb: send iso data is larger then max packet size\n");
626 /* All good copy data over */
627 memcpy(aurb
[i
].urb
.buffer
+ offset
, p
->data
, len
);
628 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
630 set_iso_buffer_used(s
, p
->devep
, offset
);
632 /* Start the stream once we have buffered enough data */
633 if (!is_iso_started(s
, p
->devep
) && i
== 1 && j
== 8) {
634 set_iso_started(s
, p
->devep
);
637 aurb
[i
].iso_frame_idx
++;
638 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
639 i
= (i
+ 1) % ISO_URB_COUNT
;
640 set_iso_urb_idx(s
, p
->devep
, i
);
644 set_iso_started(s
, p
->devep
);
646 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
650 if (is_iso_started(s
, p
->devep
)) {
651 /* (Re)-submit all fully consumed / filled urbs */
652 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
653 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
654 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, &aurb
[i
]);
656 printf("husb error submitting iso urb %d: %d\n", i
, errno
);
657 if (!in
|| len
== 0) {
669 aurb
[i
].iso_frame_idx
= -1;
677 static int usb_host_handle_data(USBDevice
*dev
, USBPacket
*p
)
679 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
680 struct usbdevfs_urb
*urb
;
686 if (!is_valid(s
, p
->devep
)) {
690 if (p
->pid
== USB_TOKEN_IN
) {
691 ep
= p
->devep
| 0x80;
696 if (is_halted(s
, p
->devep
)) {
697 ret
= ioctl(s
->fd
, USBDEVFS_CLEAR_HALT
, &ep
);
699 DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
703 clear_halt(s
, p
->devep
);
706 if (is_isoc(s
, p
->devep
)) {
707 return usb_host_handle_iso_data(s
, p
, p
->pid
== USB_TOKEN_IN
);
714 aurb
= async_alloc(s
);
719 urb
->type
= USBDEVFS_URB_TYPE_BULK
;
720 urb
->usercontext
= s
;
723 if (rem
> MAX_USBFS_BUFFER_SIZE
) {
724 urb
->buffer_length
= MAX_USBFS_BUFFER_SIZE
;
727 urb
->buffer_length
= rem
;
730 pbuf
+= urb
->buffer_length
;
731 rem
-= urb
->buffer_length
;
733 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
735 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
736 urb
->endpoint
, urb
->buffer_length
, aurb
->more
, p
, aurb
);
739 DPRINTF("husb: submit failed. errno %d\n", errno
);
747 return USB_RET_STALL
;
752 return USB_RET_ASYNC
;
755 static int ctrl_error(void)
757 if (errno
== ETIMEDOUT
) {
760 return USB_RET_STALL
;
764 static int usb_host_set_address(USBHostDevice
*s
, int addr
)
766 DPRINTF("husb: ctrl set addr %u\n", addr
);
771 static int usb_host_set_config(USBHostDevice
*s
, int config
)
773 usb_host_release_interfaces(s
);
775 int ret
= ioctl(s
->fd
, USBDEVFS_SETCONFIGURATION
, &config
);
777 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config
, ret
, errno
);
782 usb_host_claim_interfaces(s
, config
);
786 static int usb_host_set_interface(USBHostDevice
*s
, int iface
, int alt
)
788 struct usbdevfs_setinterface si
;
791 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
793 usb_host_stop_n_free_iso(s
, i
);
797 si
.interface
= iface
;
799 ret
= ioctl(s
->fd
, USBDEVFS_SETINTERFACE
, &si
);
801 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
802 iface
, alt
, ret
, errno
);
807 usb_linux_update_endp_table(s
);
811 static int usb_host_handle_control(USBDevice
*dev
, USBPacket
*p
,
812 int request
, int value
, int index
, int length
, uint8_t *data
)
814 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
815 struct usbdevfs_urb
*urb
;
820 * Process certain standard device requests.
821 * These are infrequent and are processed synchronously.
824 /* Note request is (bRequestType << 8) | bRequest */
825 DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
826 request
>> 8, request
& 0xff, value
, index
, length
);
829 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
830 return usb_host_set_address(s
, value
);
832 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
833 return usb_host_set_config(s
, value
& 0xff);
835 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
836 return usb_host_set_interface(s
, index
, value
);
839 /* The rest are asynchronous */
841 if (length
> sizeof(dev
->data_buf
)) {
842 fprintf(stderr
, "husb: ctrl buffer too small (%d > %zu)\n",
843 length
, sizeof(dev
->data_buf
));
844 return USB_RET_STALL
;
847 aurb
= async_alloc(s
);
851 * Setup ctrl transfer.
853 * s->ctrl is laid out such that data buffer immediately follows
854 * 'req' struct which is exactly what usbdevfs expects.
858 urb
->type
= USBDEVFS_URB_TYPE_CONTROL
;
859 urb
->endpoint
= p
->devep
;
861 urb
->buffer
= &dev
->setup_buf
;
862 urb
->buffer_length
= length
+ 8;
864 urb
->usercontext
= s
;
866 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
868 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb
->buffer_length
, aurb
);
871 DPRINTF("husb: submit failed. errno %d\n", errno
);
879 return USB_RET_STALL
;
883 return USB_RET_ASYNC
;
886 static int usb_linux_get_configuration(USBHostDevice
*s
)
888 uint8_t configuration
;
889 struct usb_ctrltransfer ct
;
892 if (usb_fs_type
== USB_FS_SYS
) {
893 char device_name
[32], line
[1024];
896 sprintf(device_name
, "%d-%s", s
->bus_num
, s
->port
);
898 if (!usb_host_read_file(line
, sizeof(line
), "bConfigurationValue",
902 if (sscanf(line
, "%d", &configuration
) != 1) {
905 return configuration
;
909 ct
.bRequestType
= USB_DIR_IN
;
910 ct
.bRequest
= USB_REQ_GET_CONFIGURATION
;
914 ct
.data
= &configuration
;
917 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
919 perror("usb_linux_get_configuration");
923 /* in address state */
924 if (configuration
== 0) {
928 return configuration
;
931 static uint8_t usb_linux_get_alt_setting(USBHostDevice
*s
,
932 uint8_t configuration
, uint8_t interface
)
935 struct usb_ctrltransfer ct
;
938 if (usb_fs_type
== USB_FS_SYS
) {
939 char device_name
[64], line
[1024];
942 sprintf(device_name
, "%d-%s:%d.%d", s
->bus_num
, s
->port
,
943 (int)configuration
, (int)interface
);
945 if (!usb_host_read_file(line
, sizeof(line
), "bAlternateSetting",
949 if (sscanf(line
, "%d", &alt_setting
) != 1) {
956 ct
.bRequestType
= USB_DIR_IN
| USB_RECIP_INTERFACE
;
957 ct
.bRequest
= USB_REQ_GET_INTERFACE
;
959 ct
.wIndex
= interface
;
961 ct
.data
= &alt_setting
;
963 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
965 /* Assume alt 0 on error */
972 /* returns 1 on problem encountered or 0 for success */
973 static int usb_linux_update_endp_table(USBHostDevice
*s
)
975 uint8_t *descriptors
;
976 uint8_t devep
, type
, configuration
, alt_interface
;
977 int interface
, length
, i
;
979 for (i
= 0; i
< MAX_ENDPOINTS
; i
++)
980 s
->endp_table
[i
].type
= INVALID_EP_TYPE
;
982 i
= usb_linux_get_configuration(s
);
987 /* get the desired configuration, interface, and endpoint descriptors
988 * from device description */
989 descriptors
= &s
->descr
[18];
990 length
= s
->descr_len
- 18;
993 if (descriptors
[i
+ 1] != USB_DT_CONFIG
||
994 descriptors
[i
+ 5] != configuration
) {
995 DPRINTF("invalid descriptor data - configuration\n");
1000 while (i
< length
) {
1001 if (descriptors
[i
+ 1] != USB_DT_INTERFACE
||
1002 (descriptors
[i
+ 1] == USB_DT_INTERFACE
&&
1003 descriptors
[i
+ 4] == 0)) {
1004 i
+= descriptors
[i
];
1008 interface
= descriptors
[i
+ 2];
1009 alt_interface
= usb_linux_get_alt_setting(s
, configuration
, interface
);
1011 /* the current interface descriptor is the active interface
1012 * and has endpoints */
1013 if (descriptors
[i
+ 3] != alt_interface
) {
1014 i
+= descriptors
[i
];
1018 /* advance to the endpoints */
1019 while (i
< length
&& descriptors
[i
+1] != USB_DT_ENDPOINT
) {
1020 i
+= descriptors
[i
];
1026 while (i
< length
) {
1027 if (descriptors
[i
+ 1] != USB_DT_ENDPOINT
) {
1031 devep
= descriptors
[i
+ 2];
1032 switch (descriptors
[i
+ 3] & 0x3) {
1034 type
= USBDEVFS_URB_TYPE_CONTROL
;
1037 type
= USBDEVFS_URB_TYPE_ISO
;
1038 set_max_packet_size(s
, (devep
& 0xf), descriptors
+ i
);
1041 type
= USBDEVFS_URB_TYPE_BULK
;
1044 type
= USBDEVFS_URB_TYPE_INTERRUPT
;
1047 DPRINTF("usb_host: malformed endpoint type\n");
1048 type
= USBDEVFS_URB_TYPE_BULK
;
1050 s
->endp_table
[(devep
& 0xf) - 1].type
= type
;
1051 s
->endp_table
[(devep
& 0xf) - 1].halted
= 0;
1053 i
+= descriptors
[i
];
1059 static int usb_host_open(USBHostDevice
*dev
, int bus_num
,
1060 int addr
, char *port
, const char *prod_name
, int speed
)
1065 if (dev
->fd
!= -1) {
1068 printf("husb: open device %d.%d\n", bus_num
, addr
);
1070 if (!usb_host_device_path
) {
1071 perror("husb: USB Host Device Path not set");
1074 snprintf(buf
, sizeof(buf
), "%s/%03d/%03d", usb_host_device_path
,
1076 fd
= open(buf
, O_RDWR
| O_NONBLOCK
);
1081 DPRINTF("husb: opened %s\n", buf
);
1083 dev
->bus_num
= bus_num
;
1085 strcpy(dev
->port
, port
);
1088 /* read the device description */
1089 dev
->descr_len
= read(fd
, dev
->descr
, sizeof(dev
->descr
));
1090 if (dev
->descr_len
<= 0) {
1091 perror("husb: reading device data failed");
1098 printf("=== begin dumping device descriptor data ===\n");
1099 for (x
= 0; x
< dev
->descr_len
; x
++) {
1100 printf("%02x ", dev
->descr
[x
]);
1102 printf("\n=== end dumping device descriptor data ===\n");
1108 * Initial configuration is -1 which makes us claim first
1109 * available config. We used to start with 1, which does not
1110 * always work. I've seen devices where first config starts
1113 if (!usb_host_claim_interfaces(dev
, -1)) {
1117 ret
= usb_linux_update_endp_table(dev
);
1123 struct usbdevfs_connectinfo ci
;
1125 ret
= ioctl(fd
, USBDEVFS_CONNECTINFO
, &ci
);
1127 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1132 speed
= USB_SPEED_LOW
;
1134 speed
= USB_SPEED_HIGH
;
1137 dev
->dev
.speed
= speed
;
1139 printf("husb: grabbed usb device %d.%d\n", bus_num
, addr
);
1141 if (!prod_name
|| prod_name
[0] == '\0') {
1142 snprintf(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1143 "host:%d.%d", bus_num
, addr
);
1145 pstrcpy(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1149 /* USB devio uses 'write' flag to check for async completions */
1150 qemu_set_fd_handler(dev
->fd
, NULL
, async_complete
, dev
);
1152 usb_device_attach(&dev
->dev
);
1163 static int usb_host_close(USBHostDevice
*dev
)
1167 if (dev
->fd
== -1) {
1171 qemu_set_fd_handler(dev
->fd
, NULL
, NULL
, NULL
);
1173 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
1174 if (is_isoc(dev
, i
)) {
1175 usb_host_stop_n_free_iso(dev
, i
);
1178 async_complete(dev
);
1180 usb_device_detach(&dev
->dev
);
1181 ioctl(dev
->fd
, USBDEVFS_RESET
);
1187 static void usb_host_exit_notifier(struct Notifier
* n
)
1189 USBHostDevice
*s
= container_of(n
, USBHostDevice
, exit
);
1192 ioctl(s
->fd
, USBDEVFS_RESET
);
1196 static int usb_host_initfn(USBDevice
*dev
)
1198 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
1200 dev
->auto_attach
= 0;
1202 QTAILQ_INSERT_TAIL(&hostdevs
, s
, next
);
1203 s
->exit
.notify
= usb_host_exit_notifier
;
1204 qemu_add_exit_notifier(&s
->exit
);
1205 usb_host_auto_check(NULL
);
1209 static struct USBDeviceInfo usb_host_dev_info
= {
1210 .product_desc
= "USB Host Device",
1211 .qdev
.name
= "usb-host",
1212 .qdev
.size
= sizeof(USBHostDevice
),
1213 .init
= usb_host_initfn
,
1214 .handle_packet
= usb_generic_handle_packet
,
1215 .cancel_packet
= usb_host_async_cancel
,
1216 .handle_data
= usb_host_handle_data
,
1217 .handle_control
= usb_host_handle_control
,
1218 .handle_reset
= usb_host_handle_reset
,
1219 .handle_destroy
= usb_host_handle_destroy
,
1220 .usbdevice_name
= "host",
1221 .usbdevice_init
= usb_host_device_open
,
1222 .qdev
.props
= (Property
[]) {
1223 DEFINE_PROP_UINT32("hostbus", USBHostDevice
, match
.bus_num
, 0),
1224 DEFINE_PROP_UINT32("hostaddr", USBHostDevice
, match
.addr
, 0),
1225 DEFINE_PROP_STRING("hostport", USBHostDevice
, match
.port
),
1226 DEFINE_PROP_HEX32("vendorid", USBHostDevice
, match
.vendor_id
, 0),
1227 DEFINE_PROP_HEX32("productid", USBHostDevice
, match
.product_id
, 0),
1228 DEFINE_PROP_END_OF_LIST(),
1232 static void usb_host_register_devices(void)
1234 usb_qdev_register(&usb_host_dev_info
);
1236 device_init(usb_host_register_devices
)
1238 USBDevice
*usb_host_device_open(const char *devname
)
1240 struct USBAutoFilter filter
;
1244 dev
= usb_create(NULL
/* FIXME */, "usb-host");
1246 if (strstr(devname
, "auto:")) {
1247 if (parse_filter(devname
, &filter
) < 0) {
1251 if ((p
= strchr(devname
, '.'))) {
1252 filter
.bus_num
= strtoul(devname
, NULL
, 0);
1253 filter
.addr
= strtoul(p
+ 1, NULL
, 0);
1254 filter
.vendor_id
= 0;
1255 filter
.product_id
= 0;
1256 } else if ((p
= strchr(devname
, ':'))) {
1259 filter
.vendor_id
= strtoul(devname
, NULL
, 16);
1260 filter
.product_id
= strtoul(p
+ 1, NULL
, 16);
1266 qdev_prop_set_uint32(&dev
->qdev
, "hostbus", filter
.bus_num
);
1267 qdev_prop_set_uint32(&dev
->qdev
, "hostaddr", filter
.addr
);
1268 qdev_prop_set_uint32(&dev
->qdev
, "vendorid", filter
.vendor_id
);
1269 qdev_prop_set_uint32(&dev
->qdev
, "productid", filter
.product_id
);
1270 qdev_init_nofail(&dev
->qdev
);
1274 qdev_free(&dev
->qdev
);
1278 int usb_host_device_close(const char *devname
)
1281 char product_name
[PRODUCT_NAME_SZ
];
1285 if (strstr(devname
, "auto:")) {
1286 return usb_host_auto_del(devname
);
1288 if (usb_host_find_device(&bus_num
, &addr
, product_name
,
1289 sizeof(product_name
), devname
) < 0) {
1292 s
= hostdev_find(bus_num
, addr
);
1294 usb_device_delete_addr(s
->bus_num
, s
->dev
.addr
);
1302 static int get_tag_value(char *buf
, int buf_size
,
1303 const char *str
, const char *tag
,
1304 const char *stopchars
)
1308 p
= strstr(str
, tag
);
1313 while (qemu_isspace(*p
)) {
1317 while (*p
!= '\0' && !strchr(stopchars
, *p
)) {
1318 if ((q
- buf
) < (buf_size
- 1)) {
1328 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1329 * host's USB devices. This is legacy support since many distributions
1330 * are moving to /sys/bus/usb
1332 static int usb_host_scan_dev(void *opaque
, USBScanFunc
*func
)
1337 int bus_num
, addr
, speed
, device_count
, class_id
, product_id
, vendor_id
;
1338 char product_name
[512];
1341 if (!usb_host_device_path
) {
1342 perror("husb: USB Host Device Path not set");
1345 snprintf(line
, sizeof(line
), "%s/devices", usb_host_device_path
);
1346 f
= fopen(line
, "r");
1348 perror("husb: cannot open devices file");
1353 bus_num
= addr
= class_id
= product_id
= vendor_id
= 0;
1354 speed
= -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
1356 if (fgets(line
, sizeof(line
), f
) == NULL
) {
1359 if (strlen(line
) > 0) {
1360 line
[strlen(line
) - 1] = '\0';
1362 if (line
[0] == 'T' && line
[1] == ':') {
1363 if (device_count
&& (vendor_id
|| product_id
)) {
1364 /* New device. Add the previously discovered device. */
1365 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1366 product_id
, product_name
, speed
);
1371 if (get_tag_value(buf
, sizeof(buf
), line
, "Bus=", " ") < 0) {
1374 bus_num
= atoi(buf
);
1375 if (get_tag_value(buf
, sizeof(buf
), line
, "Dev#=", " ") < 0) {
1379 if (get_tag_value(buf
, sizeof(buf
), line
, "Spd=", " ") < 0) {
1382 if (!strcmp(buf
, "5000")) {
1383 speed
= USB_SPEED_SUPER
;
1384 } else if (!strcmp(buf
, "480")) {
1385 speed
= USB_SPEED_HIGH
;
1386 } else if (!strcmp(buf
, "1.5")) {
1387 speed
= USB_SPEED_LOW
;
1389 speed
= USB_SPEED_FULL
;
1391 product_name
[0] = '\0';
1396 } else if (line
[0] == 'P' && line
[1] == ':') {
1397 if (get_tag_value(buf
, sizeof(buf
), line
, "Vendor=", " ") < 0) {
1400 vendor_id
= strtoul(buf
, NULL
, 16);
1401 if (get_tag_value(buf
, sizeof(buf
), line
, "ProdID=", " ") < 0) {
1404 product_id
= strtoul(buf
, NULL
, 16);
1405 } else if (line
[0] == 'S' && line
[1] == ':') {
1406 if (get_tag_value(buf
, sizeof(buf
), line
, "Product=", "") < 0) {
1409 pstrcpy(product_name
, sizeof(product_name
), buf
);
1410 } else if (line
[0] == 'D' && line
[1] == ':') {
1411 if (get_tag_value(buf
, sizeof(buf
), line
, "Cls=", " (") < 0) {
1414 class_id
= strtoul(buf
, NULL
, 16);
1418 if (device_count
&& (vendor_id
|| product_id
)) {
1419 /* Add the last device. */
1420 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1421 product_id
, product_name
, speed
);
1431 * Read sys file-system device file
1433 * @line address of buffer to put file contents in
1434 * @line_size size of line
1435 * @device_file path to device file (printf format string)
1436 * @device_name device being opened (inserted into device_file)
1438 * @return 0 failed, 1 succeeded ('line' contains data)
1440 static int usb_host_read_file(char *line
, size_t line_size
,
1441 const char *device_file
, const char *device_name
)
1445 char filename
[PATH_MAX
];
1447 snprintf(filename
, PATH_MAX
, USBSYSBUS_PATH
"/devices/%s/%s", device_name
,
1449 f
= fopen(filename
, "r");
1451 ret
= fgets(line
, line_size
, f
) != NULL
;
1459 * Use /sys/bus/usb/devices/ directory to determine host's USB
1462 * This code is based on Robert Schiele's original patches posted to
1463 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1465 static int usb_host_scan_sys(void *opaque
, USBScanFunc
*func
)
1469 int bus_num
, addr
, speed
, class_id
, product_id
, vendor_id
;
1471 char port
[MAX_PORTLEN
];
1472 char product_name
[512];
1475 dir
= opendir(USBSYSBUS_PATH
"/devices");
1477 perror("husb: cannot open devices directory");
1481 while ((de
= readdir(dir
))) {
1482 if (de
->d_name
[0] != '.' && !strchr(de
->d_name
, ':')) {
1483 if (sscanf(de
->d_name
, "%d-%7[0-9.]", &bus_num
, port
) < 2) {
1487 if (!usb_host_read_file(line
, sizeof(line
), "devnum", de
->d_name
)) {
1490 if (sscanf(line
, "%d", &addr
) != 1) {
1493 if (!usb_host_read_file(line
, sizeof(line
), "bDeviceClass",
1497 if (sscanf(line
, "%x", &class_id
) != 1) {
1501 if (!usb_host_read_file(line
, sizeof(line
), "idVendor",
1505 if (sscanf(line
, "%x", &vendor_id
) != 1) {
1508 if (!usb_host_read_file(line
, sizeof(line
), "idProduct",
1512 if (sscanf(line
, "%x", &product_id
) != 1) {
1515 if (!usb_host_read_file(line
, sizeof(line
), "product",
1519 if (strlen(line
) > 0) {
1520 line
[strlen(line
) - 1] = '\0';
1522 pstrcpy(product_name
, sizeof(product_name
), line
);
1525 if (!usb_host_read_file(line
, sizeof(line
), "speed", de
->d_name
)) {
1528 if (!strcmp(line
, "5000\n")) {
1529 speed
= USB_SPEED_SUPER
;
1530 } else if (!strcmp(line
, "480\n")) {
1531 speed
= USB_SPEED_HIGH
;
1532 } else if (!strcmp(line
, "1.5\n")) {
1533 speed
= USB_SPEED_LOW
;
1535 speed
= USB_SPEED_FULL
;
1538 ret
= func(opaque
, bus_num
, addr
, port
, class_id
, vendor_id
,
1539 product_id
, product_name
, speed
);
1553 * Determine how to access the host's USB devices and call the
1554 * specific support function.
1556 static int usb_host_scan(void *opaque
, USBScanFunc
*func
)
1558 Monitor
*mon
= cur_mon
;
1562 const char *fs_type
[] = {"unknown", "proc", "dev", "sys"};
1563 char devpath
[PATH_MAX
];
1565 /* only check the host once */
1567 dir
= opendir(USBSYSBUS_PATH
"/devices");
1569 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1570 strcpy(devpath
, USBDEVBUS_PATH
);
1571 usb_fs_type
= USB_FS_SYS
;
1573 DPRINTF(USBDBG_DEVOPENED
, USBSYSBUS_PATH
);
1576 f
= fopen(USBPROCBUS_PATH
"/devices", "r");
1578 /* devices found in /proc/bus/usb/ */
1579 strcpy(devpath
, USBPROCBUS_PATH
);
1580 usb_fs_type
= USB_FS_PROC
;
1582 DPRINTF(USBDBG_DEVOPENED
, USBPROCBUS_PATH
);
1585 /* try additional methods if an access method hasn't been found yet */
1586 f
= fopen(USBDEVBUS_PATH
"/devices", "r");
1588 /* devices found in /dev/bus/usb/ */
1589 strcpy(devpath
, USBDEVBUS_PATH
);
1590 usb_fs_type
= USB_FS_DEV
;
1592 DPRINTF(USBDBG_DEVOPENED
, USBDEVBUS_PATH
);
1598 monitor_printf(mon
, "husb: unable to access USB devices\n");
1603 /* the module setting (used later for opening devices) */
1604 usb_host_device_path
= qemu_mallocz(strlen(devpath
)+1);
1605 strcpy(usb_host_device_path
, devpath
);
1607 monitor_printf(mon
, "husb: using %s file-system with %s\n",
1608 fs_type
[usb_fs_type
], usb_host_device_path
);
1612 switch (usb_fs_type
) {
1615 ret
= usb_host_scan_dev(opaque
, func
);
1618 ret
= usb_host_scan_sys(opaque
, func
);
1627 static QEMUTimer
*usb_auto_timer
;
1629 static int usb_host_auto_scan(void *opaque
, int bus_num
, int addr
, char *port
,
1630 int class_id
, int vendor_id
, int product_id
,
1631 const char *product_name
, int speed
)
1633 struct USBAutoFilter
*f
;
1634 struct USBHostDevice
*s
;
1640 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1643 if (f
->bus_num
> 0 && f
->bus_num
!= bus_num
) {
1646 if (f
->addr
> 0 && f
->addr
!= addr
) {
1649 if (f
->port
!= NULL
&& (port
== NULL
|| strcmp(f
->port
, port
) != 0)) {
1653 if (f
->vendor_id
> 0 && f
->vendor_id
!= vendor_id
) {
1657 if (f
->product_id
> 0 && f
->product_id
!= product_id
) {
1660 /* We got a match */
1662 /* Already attached ? */
1666 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num
, addr
);
1668 usb_host_open(s
, bus_num
, addr
, port
, product_name
, speed
);
1674 static void usb_host_auto_check(void *unused
)
1676 struct USBHostDevice
*s
;
1677 int unconnected
= 0;
1679 usb_host_scan(NULL
, usb_host_auto_scan
);
1681 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1687 if (unconnected
== 0) {
1688 /* nothing to watch */
1689 if (usb_auto_timer
) {
1690 qemu_del_timer(usb_auto_timer
);
1695 if (!usb_auto_timer
) {
1696 usb_auto_timer
= qemu_new_timer_ms(rt_clock
, usb_host_auto_check
, NULL
);
1697 if (!usb_auto_timer
) {
1701 qemu_mod_timer(usb_auto_timer
, qemu_get_clock_ms(rt_clock
) + 2000);
1705 * Autoconnect filter
1707 * auto:bus:dev[:vid:pid]
1708 * auto:bus.dev[:vid:pid]
1710 * bus - bus number (dec, * means any)
1711 * dev - device number (dec, * means any)
1712 * vid - vendor id (hex, * means any)
1713 * pid - product id (hex, * means any)
1715 * See 'lsusb' output.
1717 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
)
1719 enum { BUS
, DEV
, VID
, PID
, DONE
};
1720 const char *p
= spec
;
1728 for (i
= BUS
; i
< DONE
; i
++) {
1729 p
= strpbrk(p
, ":.");
1739 case BUS
: f
->bus_num
= strtol(p
, NULL
, 10); break;
1740 case DEV
: f
->addr
= strtol(p
, NULL
, 10); break;
1741 case VID
: f
->vendor_id
= strtol(p
, NULL
, 16); break;
1742 case PID
: f
->product_id
= strtol(p
, NULL
, 16); break;
1747 fprintf(stderr
, "husb: invalid auto filter spec %s\n", spec
);
1754 /**********************/
1755 /* USB host device info */
1757 struct usb_class_info
{
1759 const char *class_name
;
1762 static const struct usb_class_info usb_class_info
[] = {
1763 { USB_CLASS_AUDIO
, "Audio"},
1764 { USB_CLASS_COMM
, "Communication"},
1765 { USB_CLASS_HID
, "HID"},
1766 { USB_CLASS_HUB
, "Hub" },
1767 { USB_CLASS_PHYSICAL
, "Physical" },
1768 { USB_CLASS_PRINTER
, "Printer" },
1769 { USB_CLASS_MASS_STORAGE
, "Storage" },
1770 { USB_CLASS_CDC_DATA
, "Data" },
1771 { USB_CLASS_APP_SPEC
, "Application Specific" },
1772 { USB_CLASS_VENDOR_SPEC
, "Vendor Specific" },
1773 { USB_CLASS_STILL_IMAGE
, "Still Image" },
1774 { USB_CLASS_CSCID
, "Smart Card" },
1775 { USB_CLASS_CONTENT_SEC
, "Content Security" },
1779 static const char *usb_class_str(uint8_t class)
1781 const struct usb_class_info
*p
;
1782 for(p
= usb_class_info
; p
->class != -1; p
++) {
1783 if (p
->class == class) {
1787 return p
->class_name
;
1790 static void usb_info_device(Monitor
*mon
, int bus_num
, int addr
, char *port
,
1791 int class_id
, int vendor_id
, int product_id
,
1792 const char *product_name
,
1795 const char *class_str
, *speed_str
;
1801 case USB_SPEED_FULL
:
1804 case USB_SPEED_HIGH
:
1807 case USB_SPEED_SUPER
:
1815 monitor_printf(mon
, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1816 bus_num
, addr
, port
, speed_str
);
1817 class_str
= usb_class_str(class_id
);
1819 monitor_printf(mon
, " %s:", class_str
);
1821 monitor_printf(mon
, " Class %02x:", class_id
);
1823 monitor_printf(mon
, " USB device %04x:%04x", vendor_id
, product_id
);
1824 if (product_name
[0] != '\0') {
1825 monitor_printf(mon
, ", %s", product_name
);
1827 monitor_printf(mon
, "\n");
1830 static int usb_host_info_device(void *opaque
, int bus_num
, int addr
,
1831 char *path
, int class_id
,
1832 int vendor_id
, int product_id
,
1833 const char *product_name
,
1836 Monitor
*mon
= opaque
;
1838 usb_info_device(mon
, bus_num
, addr
, path
, class_id
, vendor_id
, product_id
,
1839 product_name
, speed
);
1843 static void dec2str(int val
, char *str
, size_t size
)
1846 snprintf(str
, size
, "*");
1848 snprintf(str
, size
, "%d", val
);
1852 static void hex2str(int val
, char *str
, size_t size
)
1855 snprintf(str
, size
, "*");
1857 snprintf(str
, size
, "%04x", val
);
1861 void usb_host_info(Monitor
*mon
)
1863 struct USBAutoFilter
*f
;
1864 struct USBHostDevice
*s
;
1866 usb_host_scan(mon
, usb_host_info_device
);
1868 if (QTAILQ_EMPTY(&hostdevs
)) {
1872 monitor_printf(mon
, " Auto filters:\n");
1873 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1874 char bus
[10], addr
[10], vid
[10], pid
[10];
1876 dec2str(f
->bus_num
, bus
, sizeof(bus
));
1877 dec2str(f
->addr
, addr
, sizeof(addr
));
1878 hex2str(f
->vendor_id
, vid
, sizeof(vid
));
1879 hex2str(f
->product_id
, pid
, sizeof(pid
));
1880 monitor_printf(mon
, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1881 bus
, addr
, f
->port
? f
->port
: "*", vid
, pid
);