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
) {
383 while (i
< dev
->descr_len
) {
384 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
386 dev
->descr
[i
], dev
->descr
[i
+1]);
388 if (dev
->descr
[i
+1] != USB_DT_CONFIG
) {
392 config_descr_len
= dev
->descr
[i
];
394 printf("husb: config #%d need %d\n", dev
->descr
[i
+ 5], configuration
);
396 if (configuration
< 0 || configuration
== dev
->descr
[i
+ 5]) {
397 configuration
= dev
->descr
[i
+ 5];
401 i
+= config_descr_len
;
404 if (i
>= dev
->descr_len
) {
406 "husb: update iface failed. no matching configuration\n");
409 nb_interfaces
= dev
->descr
[i
+ 4];
411 #ifdef USBDEVFS_DISCONNECT
412 /* earlier Linux 2.4 do not support that */
414 struct usbdevfs_ioctl ctrl
;
415 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
416 ctrl
.ioctl_code
= USBDEVFS_DISCONNECT
;
417 ctrl
.ifno
= interface
;
419 op
= "USBDEVFS_DISCONNECT";
420 ret
= ioctl(dev
->fd
, USBDEVFS_IOCTL
, &ctrl
);
421 if (ret
< 0 && errno
!= ENODATA
) {
428 /* XXX: only grab if all interfaces are free */
429 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
430 op
= "USBDEVFS_CLAIMINTERFACE";
431 ret
= ioctl(dev
->fd
, USBDEVFS_CLAIMINTERFACE
, &interface
);
433 if (errno
== EBUSY
) {
434 printf("husb: update iface. device already grabbed\n");
436 perror("husb: failed to claim interface");
442 printf("husb: %d interfaces claimed for configuration %d\n",
443 nb_interfaces
, configuration
);
445 dev
->ninterfaces
= nb_interfaces
;
446 dev
->configuration
= configuration
;
450 if (errno
== ENODEV
) {
457 static int usb_host_release_interfaces(USBHostDevice
*s
)
461 DPRINTF("husb: releasing interfaces\n");
463 for (i
= 0; i
< s
->ninterfaces
; i
++) {
464 ret
= ioctl(s
->fd
, USBDEVFS_RELEASEINTERFACE
, &i
);
466 perror("husb: failed to release interface");
474 static void usb_host_handle_reset(USBDevice
*dev
)
476 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
478 DPRINTF("husb: reset device %u.%u\n", s
->bus_num
, s
->addr
);
480 ioctl(s
->fd
, USBDEVFS_RESET
);
482 usb_host_claim_interfaces(s
, s
->configuration
);
485 static void usb_host_handle_destroy(USBDevice
*dev
)
487 USBHostDevice
*s
= (USBHostDevice
*)dev
;
490 QTAILQ_REMOVE(&hostdevs
, s
, next
);
491 qemu_remove_exit_notifier(&s
->exit
);
494 static int usb_linux_update_endp_table(USBHostDevice
*s
);
496 /* iso data is special, we need to keep enough urbs in flight to make sure
497 that the controller never runs out of them, otherwise the device will
498 likely suffer a buffer underrun / overrun. */
499 static AsyncURB
*usb_host_alloc_iso(USBHostDevice
*s
, uint8_t ep
, int in
)
502 int i
, j
, len
= get_max_packet_size(s
, ep
);
504 aurb
= qemu_mallocz(ISO_URB_COUNT
* sizeof(*aurb
));
505 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
506 aurb
[i
].urb
.endpoint
= ep
;
507 aurb
[i
].urb
.buffer_length
= ISO_FRAME_DESC_PER_URB
* len
;
508 aurb
[i
].urb
.buffer
= qemu_malloc(aurb
[i
].urb
.buffer_length
);
509 aurb
[i
].urb
.type
= USBDEVFS_URB_TYPE_ISO
;
510 aurb
[i
].urb
.flags
= USBDEVFS_URB_ISO_ASAP
;
511 aurb
[i
].urb
.number_of_packets
= ISO_FRAME_DESC_PER_URB
;
512 for (j
= 0 ; j
< ISO_FRAME_DESC_PER_URB
; j
++)
513 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
515 aurb
[i
].urb
.endpoint
|= 0x80;
516 /* Mark as fully consumed (idle) */
517 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
;
520 set_iso_urb(s
, ep
, aurb
);
525 static void usb_host_stop_n_free_iso(USBHostDevice
*s
, uint8_t ep
)
528 int i
, ret
, killed
= 0, free
= 1;
530 aurb
= get_iso_urb(s
, ep
);
535 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
537 if (aurb
[i
].iso_frame_idx
== -1) {
538 ret
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, &aurb
[i
]);
540 printf("husb: discard isoc in urb failed errno %d\n", errno
);
548 /* Make sure any urbs we've killed are reaped before we free them */
553 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
554 qemu_free(aurb
[i
].urb
.buffer
);
560 printf("husb: leaking iso urbs because of discard failure\n");
561 set_iso_urb(s
, ep
, NULL
);
562 set_iso_urb_idx(s
, ep
, 0);
563 clear_iso_started(s
, ep
);
566 static int urb_status_to_usb_ret(int status
)
570 return USB_RET_STALL
;
576 static int usb_host_handle_iso_data(USBHostDevice
*s
, USBPacket
*p
, int in
)
579 int i
, j
, ret
, max_packet_size
, offset
, len
= 0;
581 max_packet_size
= get_max_packet_size(s
, p
->devep
);
582 if (max_packet_size
== 0)
585 aurb
= get_iso_urb(s
, p
->devep
);
587 aurb
= usb_host_alloc_iso(s
, p
->devep
, in
);
590 i
= get_iso_urb_idx(s
, p
->devep
);
591 j
= aurb
[i
].iso_frame_idx
;
592 if (j
>= 0 && j
< ISO_FRAME_DESC_PER_URB
) {
594 /* Check urb status */
595 if (aurb
[i
].urb
.status
) {
596 len
= urb_status_to_usb_ret(aurb
[i
].urb
.status
);
597 /* Move to the next urb */
598 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
- 1;
599 /* Check frame status */
600 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].status
) {
601 len
= urb_status_to_usb_ret(
602 aurb
[i
].urb
.iso_frame_desc
[j
].status
);
603 /* Check the frame fits */
604 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
> p
->len
) {
605 printf("husb: received iso data is larger then packet\n");
607 /* All good copy data over */
609 len
= aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
;
612 j
* aurb
[i
].urb
.iso_frame_desc
[0].length
,
617 offset
= (j
== 0) ? 0 : get_iso_buffer_used(s
, p
->devep
);
619 /* Check the frame fits */
620 if (len
> max_packet_size
) {
621 printf("husb: send iso data is larger then max packet size\n");
625 /* All good copy data over */
626 memcpy(aurb
[i
].urb
.buffer
+ offset
, p
->data
, len
);
627 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
629 set_iso_buffer_used(s
, p
->devep
, offset
);
631 /* Start the stream once we have buffered enough data */
632 if (!is_iso_started(s
, p
->devep
) && i
== 1 && j
== 8) {
633 set_iso_started(s
, p
->devep
);
636 aurb
[i
].iso_frame_idx
++;
637 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
638 i
= (i
+ 1) % ISO_URB_COUNT
;
639 set_iso_urb_idx(s
, p
->devep
, i
);
643 set_iso_started(s
, p
->devep
);
645 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
649 if (is_iso_started(s
, p
->devep
)) {
650 /* (Re)-submit all fully consumed / filled urbs */
651 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
652 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
653 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, &aurb
[i
]);
655 printf("husb error submitting iso urb %d: %d\n", i
, errno
);
656 if (!in
|| len
== 0) {
668 aurb
[i
].iso_frame_idx
= -1;
676 static int usb_host_handle_data(USBDevice
*dev
, USBPacket
*p
)
678 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
679 struct usbdevfs_urb
*urb
;
685 if (!is_valid(s
, p
->devep
)) {
689 if (p
->pid
== USB_TOKEN_IN
) {
690 ep
= p
->devep
| 0x80;
695 if (is_halted(s
, p
->devep
)) {
696 ret
= ioctl(s
->fd
, USBDEVFS_CLEAR_HALT
, &ep
);
698 DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
702 clear_halt(s
, p
->devep
);
705 if (is_isoc(s
, p
->devep
)) {
706 return usb_host_handle_iso_data(s
, p
, p
->pid
== USB_TOKEN_IN
);
713 aurb
= async_alloc(s
);
718 urb
->type
= USBDEVFS_URB_TYPE_BULK
;
719 urb
->usercontext
= s
;
722 if (rem
> MAX_USBFS_BUFFER_SIZE
) {
723 urb
->buffer_length
= MAX_USBFS_BUFFER_SIZE
;
726 urb
->buffer_length
= rem
;
729 pbuf
+= urb
->buffer_length
;
730 rem
-= urb
->buffer_length
;
732 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
734 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
735 urb
->endpoint
, urb
->buffer_length
, aurb
->more
, p
, aurb
);
738 DPRINTF("husb: submit failed. errno %d\n", errno
);
746 return USB_RET_STALL
;
751 return USB_RET_ASYNC
;
754 static int ctrl_error(void)
756 if (errno
== ETIMEDOUT
) {
759 return USB_RET_STALL
;
763 static int usb_host_set_address(USBHostDevice
*s
, int addr
)
765 DPRINTF("husb: ctrl set addr %u\n", addr
);
770 static int usb_host_set_config(USBHostDevice
*s
, int config
)
772 usb_host_release_interfaces(s
);
774 int ret
= ioctl(s
->fd
, USBDEVFS_SETCONFIGURATION
, &config
);
776 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config
, ret
, errno
);
781 usb_host_claim_interfaces(s
, config
);
785 static int usb_host_set_interface(USBHostDevice
*s
, int iface
, int alt
)
787 struct usbdevfs_setinterface si
;
790 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
792 usb_host_stop_n_free_iso(s
, i
);
796 si
.interface
= iface
;
798 ret
= ioctl(s
->fd
, USBDEVFS_SETINTERFACE
, &si
);
800 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
801 iface
, alt
, ret
, errno
);
806 usb_linux_update_endp_table(s
);
810 static int usb_host_handle_control(USBDevice
*dev
, USBPacket
*p
,
811 int request
, int value
, int index
, int length
, uint8_t *data
)
813 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
814 struct usbdevfs_urb
*urb
;
819 * Process certain standard device requests.
820 * These are infrequent and are processed synchronously.
823 /* Note request is (bRequestType << 8) | bRequest */
824 DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
825 request
>> 8, request
& 0xff, value
, index
, length
);
828 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
829 return usb_host_set_address(s
, value
);
831 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
832 return usb_host_set_config(s
, value
& 0xff);
834 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
835 return usb_host_set_interface(s
, index
, value
);
838 /* The rest are asynchronous */
840 if (length
> sizeof(dev
->data_buf
)) {
841 fprintf(stderr
, "husb: ctrl buffer too small (%d > %zu)\n",
842 length
, sizeof(dev
->data_buf
));
843 return USB_RET_STALL
;
846 aurb
= async_alloc(s
);
850 * Setup ctrl transfer.
852 * s->ctrl is laid out such that data buffer immediately follows
853 * 'req' struct which is exactly what usbdevfs expects.
857 urb
->type
= USBDEVFS_URB_TYPE_CONTROL
;
858 urb
->endpoint
= p
->devep
;
860 urb
->buffer
= &dev
->setup_buf
;
861 urb
->buffer_length
= length
+ 8;
863 urb
->usercontext
= s
;
865 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
867 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb
->buffer_length
, aurb
);
870 DPRINTF("husb: submit failed. errno %d\n", errno
);
878 return USB_RET_STALL
;
882 return USB_RET_ASYNC
;
885 static int usb_linux_get_configuration(USBHostDevice
*s
)
887 uint8_t configuration
;
888 struct usb_ctrltransfer ct
;
891 if (usb_fs_type
== USB_FS_SYS
) {
892 char device_name
[32], line
[1024];
895 sprintf(device_name
, "%d-%s", s
->bus_num
, s
->port
);
897 if (!usb_host_read_file(line
, sizeof(line
), "bConfigurationValue",
901 if (sscanf(line
, "%d", &configuration
) != 1) {
904 return configuration
;
908 ct
.bRequestType
= USB_DIR_IN
;
909 ct
.bRequest
= USB_REQ_GET_CONFIGURATION
;
913 ct
.data
= &configuration
;
916 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
918 perror("usb_linux_get_configuration");
922 /* in address state */
923 if (configuration
== 0) {
927 return configuration
;
930 static uint8_t usb_linux_get_alt_setting(USBHostDevice
*s
,
931 uint8_t configuration
, uint8_t interface
)
934 struct usb_ctrltransfer ct
;
937 if (usb_fs_type
== USB_FS_SYS
) {
938 char device_name
[64], line
[1024];
941 sprintf(device_name
, "%d-%s:%d.%d", s
->bus_num
, s
->port
,
942 (int)configuration
, (int)interface
);
944 if (!usb_host_read_file(line
, sizeof(line
), "bAlternateSetting",
948 if (sscanf(line
, "%d", &alt_setting
) != 1) {
955 ct
.bRequestType
= USB_DIR_IN
| USB_RECIP_INTERFACE
;
956 ct
.bRequest
= USB_REQ_GET_INTERFACE
;
958 ct
.wIndex
= interface
;
960 ct
.data
= &alt_setting
;
962 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
964 /* Assume alt 0 on error */
971 /* returns 1 on problem encountered or 0 for success */
972 static int usb_linux_update_endp_table(USBHostDevice
*s
)
974 uint8_t *descriptors
;
975 uint8_t devep
, type
, configuration
, alt_interface
;
976 int interface
, length
, i
;
978 for (i
= 0; i
< MAX_ENDPOINTS
; i
++)
979 s
->endp_table
[i
].type
= INVALID_EP_TYPE
;
981 i
= usb_linux_get_configuration(s
);
986 /* get the desired configuration, interface, and endpoint descriptors
987 * from device description */
988 descriptors
= &s
->descr
[18];
989 length
= s
->descr_len
- 18;
992 if (descriptors
[i
+ 1] != USB_DT_CONFIG
||
993 descriptors
[i
+ 5] != configuration
) {
994 DPRINTF("invalid descriptor data - configuration\n");
1000 if (descriptors
[i
+ 1] != USB_DT_INTERFACE
||
1001 (descriptors
[i
+ 1] == USB_DT_INTERFACE
&&
1002 descriptors
[i
+ 4] == 0)) {
1003 i
+= descriptors
[i
];
1007 interface
= descriptors
[i
+ 2];
1008 alt_interface
= usb_linux_get_alt_setting(s
, configuration
, interface
);
1010 /* the current interface descriptor is the active interface
1011 * and has endpoints */
1012 if (descriptors
[i
+ 3] != alt_interface
) {
1013 i
+= descriptors
[i
];
1017 /* advance to the endpoints */
1018 while (i
< length
&& descriptors
[i
+1] != USB_DT_ENDPOINT
) {
1019 i
+= descriptors
[i
];
1025 while (i
< length
) {
1026 if (descriptors
[i
+ 1] != USB_DT_ENDPOINT
) {
1030 devep
= descriptors
[i
+ 2];
1031 switch (descriptors
[i
+ 3] & 0x3) {
1033 type
= USBDEVFS_URB_TYPE_CONTROL
;
1036 type
= USBDEVFS_URB_TYPE_ISO
;
1037 set_max_packet_size(s
, (devep
& 0xf), descriptors
+ i
);
1040 type
= USBDEVFS_URB_TYPE_BULK
;
1043 type
= USBDEVFS_URB_TYPE_INTERRUPT
;
1046 DPRINTF("usb_host: malformed endpoint type\n");
1047 type
= USBDEVFS_URB_TYPE_BULK
;
1049 s
->endp_table
[(devep
& 0xf) - 1].type
= type
;
1050 s
->endp_table
[(devep
& 0xf) - 1].halted
= 0;
1052 i
+= descriptors
[i
];
1058 static int usb_host_open(USBHostDevice
*dev
, int bus_num
,
1059 int addr
, char *port
, const char *prod_name
, int speed
)
1064 if (dev
->fd
!= -1) {
1067 printf("husb: open device %d.%d\n", bus_num
, addr
);
1069 if (!usb_host_device_path
) {
1070 perror("husb: USB Host Device Path not set");
1073 snprintf(buf
, sizeof(buf
), "%s/%03d/%03d", usb_host_device_path
,
1075 fd
= open(buf
, O_RDWR
| O_NONBLOCK
);
1080 DPRINTF("husb: opened %s\n", buf
);
1082 dev
->bus_num
= bus_num
;
1084 strcpy(dev
->port
, port
);
1087 /* read the device description */
1088 dev
->descr_len
= read(fd
, dev
->descr
, sizeof(dev
->descr
));
1089 if (dev
->descr_len
<= 0) {
1090 perror("husb: reading device data failed");
1097 printf("=== begin dumping device descriptor data ===\n");
1098 for (x
= 0; x
< dev
->descr_len
; x
++) {
1099 printf("%02x ", dev
->descr
[x
]);
1101 printf("\n=== end dumping device descriptor data ===\n");
1107 * Initial configuration is -1 which makes us claim first
1108 * available config. We used to start with 1, which does not
1109 * always work. I've seen devices where first config starts
1112 if (!usb_host_claim_interfaces(dev
, -1)) {
1116 ret
= usb_linux_update_endp_table(dev
);
1122 struct usbdevfs_connectinfo ci
;
1124 ret
= ioctl(fd
, USBDEVFS_CONNECTINFO
, &ci
);
1126 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1131 speed
= USB_SPEED_LOW
;
1133 speed
= USB_SPEED_HIGH
;
1136 dev
->dev
.speed
= speed
;
1138 printf("husb: grabbed usb device %d.%d\n", bus_num
, addr
);
1140 if (!prod_name
|| prod_name
[0] == '\0') {
1141 snprintf(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1142 "host:%d.%d", bus_num
, addr
);
1144 pstrcpy(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1148 /* USB devio uses 'write' flag to check for async completions */
1149 qemu_set_fd_handler(dev
->fd
, NULL
, async_complete
, dev
);
1151 usb_device_attach(&dev
->dev
);
1162 static int usb_host_close(USBHostDevice
*dev
)
1166 if (dev
->fd
== -1) {
1170 qemu_set_fd_handler(dev
->fd
, NULL
, NULL
, NULL
);
1172 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
1173 if (is_isoc(dev
, i
)) {
1174 usb_host_stop_n_free_iso(dev
, i
);
1177 async_complete(dev
);
1179 usb_device_detach(&dev
->dev
);
1180 ioctl(dev
->fd
, USBDEVFS_RESET
);
1186 static void usb_host_exit_notifier(struct Notifier
* n
)
1188 USBHostDevice
*s
= container_of(n
, USBHostDevice
, exit
);
1191 ioctl(s
->fd
, USBDEVFS_RESET
);
1195 static int usb_host_initfn(USBDevice
*dev
)
1197 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
1199 dev
->auto_attach
= 0;
1201 QTAILQ_INSERT_TAIL(&hostdevs
, s
, next
);
1202 s
->exit
.notify
= usb_host_exit_notifier
;
1203 qemu_add_exit_notifier(&s
->exit
);
1204 usb_host_auto_check(NULL
);
1208 static struct USBDeviceInfo usb_host_dev_info
= {
1209 .product_desc
= "USB Host Device",
1210 .qdev
.name
= "usb-host",
1211 .qdev
.size
= sizeof(USBHostDevice
),
1212 .init
= usb_host_initfn
,
1213 .handle_packet
= usb_generic_handle_packet
,
1214 .cancel_packet
= usb_host_async_cancel
,
1215 .handle_data
= usb_host_handle_data
,
1216 .handle_control
= usb_host_handle_control
,
1217 .handle_reset
= usb_host_handle_reset
,
1218 .handle_destroy
= usb_host_handle_destroy
,
1219 .usbdevice_name
= "host",
1220 .usbdevice_init
= usb_host_device_open
,
1221 .qdev
.props
= (Property
[]) {
1222 DEFINE_PROP_UINT32("hostbus", USBHostDevice
, match
.bus_num
, 0),
1223 DEFINE_PROP_UINT32("hostaddr", USBHostDevice
, match
.addr
, 0),
1224 DEFINE_PROP_STRING("hostport", USBHostDevice
, match
.port
),
1225 DEFINE_PROP_HEX32("vendorid", USBHostDevice
, match
.vendor_id
, 0),
1226 DEFINE_PROP_HEX32("productid", USBHostDevice
, match
.product_id
, 0),
1227 DEFINE_PROP_END_OF_LIST(),
1231 static void usb_host_register_devices(void)
1233 usb_qdev_register(&usb_host_dev_info
);
1235 device_init(usb_host_register_devices
)
1237 USBDevice
*usb_host_device_open(const char *devname
)
1239 struct USBAutoFilter filter
;
1243 dev
= usb_create(NULL
/* FIXME */, "usb-host");
1245 if (strstr(devname
, "auto:")) {
1246 if (parse_filter(devname
, &filter
) < 0) {
1250 if ((p
= strchr(devname
, '.'))) {
1251 filter
.bus_num
= strtoul(devname
, NULL
, 0);
1252 filter
.addr
= strtoul(p
+ 1, NULL
, 0);
1253 filter
.vendor_id
= 0;
1254 filter
.product_id
= 0;
1255 } else if ((p
= strchr(devname
, ':'))) {
1258 filter
.vendor_id
= strtoul(devname
, NULL
, 16);
1259 filter
.product_id
= strtoul(p
+ 1, NULL
, 16);
1265 qdev_prop_set_uint32(&dev
->qdev
, "hostbus", filter
.bus_num
);
1266 qdev_prop_set_uint32(&dev
->qdev
, "hostaddr", filter
.addr
);
1267 qdev_prop_set_uint32(&dev
->qdev
, "vendorid", filter
.vendor_id
);
1268 qdev_prop_set_uint32(&dev
->qdev
, "productid", filter
.product_id
);
1269 qdev_init_nofail(&dev
->qdev
);
1273 qdev_free(&dev
->qdev
);
1277 int usb_host_device_close(const char *devname
)
1280 char product_name
[PRODUCT_NAME_SZ
];
1284 if (strstr(devname
, "auto:")) {
1285 return usb_host_auto_del(devname
);
1287 if (usb_host_find_device(&bus_num
, &addr
, product_name
,
1288 sizeof(product_name
), devname
) < 0) {
1291 s
= hostdev_find(bus_num
, addr
);
1293 usb_device_delete_addr(s
->bus_num
, s
->dev
.addr
);
1301 static int get_tag_value(char *buf
, int buf_size
,
1302 const char *str
, const char *tag
,
1303 const char *stopchars
)
1307 p
= strstr(str
, tag
);
1312 while (qemu_isspace(*p
)) {
1316 while (*p
!= '\0' && !strchr(stopchars
, *p
)) {
1317 if ((q
- buf
) < (buf_size
- 1)) {
1327 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1328 * host's USB devices. This is legacy support since many distributions
1329 * are moving to /sys/bus/usb
1331 static int usb_host_scan_dev(void *opaque
, USBScanFunc
*func
)
1336 int bus_num
, addr
, speed
, device_count
, class_id
, product_id
, vendor_id
;
1337 char product_name
[512];
1340 if (!usb_host_device_path
) {
1341 perror("husb: USB Host Device Path not set");
1344 snprintf(line
, sizeof(line
), "%s/devices", usb_host_device_path
);
1345 f
= fopen(line
, "r");
1347 perror("husb: cannot open devices file");
1352 bus_num
= addr
= class_id
= product_id
= vendor_id
= 0;
1353 speed
= -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
1355 if (fgets(line
, sizeof(line
), f
) == NULL
) {
1358 if (strlen(line
) > 0) {
1359 line
[strlen(line
) - 1] = '\0';
1361 if (line
[0] == 'T' && line
[1] == ':') {
1362 if (device_count
&& (vendor_id
|| product_id
)) {
1363 /* New device. Add the previously discovered device. */
1364 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1365 product_id
, product_name
, speed
);
1370 if (get_tag_value(buf
, sizeof(buf
), line
, "Bus=", " ") < 0) {
1373 bus_num
= atoi(buf
);
1374 if (get_tag_value(buf
, sizeof(buf
), line
, "Dev#=", " ") < 0) {
1378 if (get_tag_value(buf
, sizeof(buf
), line
, "Spd=", " ") < 0) {
1381 if (!strcmp(buf
, "480")) {
1382 speed
= USB_SPEED_HIGH
;
1383 } else if (!strcmp(buf
, "1.5")) {
1384 speed
= USB_SPEED_LOW
;
1386 speed
= USB_SPEED_FULL
;
1388 product_name
[0] = '\0';
1393 } else if (line
[0] == 'P' && line
[1] == ':') {
1394 if (get_tag_value(buf
, sizeof(buf
), line
, "Vendor=", " ") < 0) {
1397 vendor_id
= strtoul(buf
, NULL
, 16);
1398 if (get_tag_value(buf
, sizeof(buf
), line
, "ProdID=", " ") < 0) {
1401 product_id
= strtoul(buf
, NULL
, 16);
1402 } else if (line
[0] == 'S' && line
[1] == ':') {
1403 if (get_tag_value(buf
, sizeof(buf
), line
, "Product=", "") < 0) {
1406 pstrcpy(product_name
, sizeof(product_name
), buf
);
1407 } else if (line
[0] == 'D' && line
[1] == ':') {
1408 if (get_tag_value(buf
, sizeof(buf
), line
, "Cls=", " (") < 0) {
1411 class_id
= strtoul(buf
, NULL
, 16);
1415 if (device_count
&& (vendor_id
|| product_id
)) {
1416 /* Add the last device. */
1417 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1418 product_id
, product_name
, speed
);
1428 * Read sys file-system device file
1430 * @line address of buffer to put file contents in
1431 * @line_size size of line
1432 * @device_file path to device file (printf format string)
1433 * @device_name device being opened (inserted into device_file)
1435 * @return 0 failed, 1 succeeded ('line' contains data)
1437 static int usb_host_read_file(char *line
, size_t line_size
,
1438 const char *device_file
, const char *device_name
)
1442 char filename
[PATH_MAX
];
1444 snprintf(filename
, PATH_MAX
, USBSYSBUS_PATH
"/devices/%s/%s", device_name
,
1446 f
= fopen(filename
, "r");
1448 ret
= fgets(line
, line_size
, f
) != NULL
;
1456 * Use /sys/bus/usb/devices/ directory to determine host's USB
1459 * This code is based on Robert Schiele's original patches posted to
1460 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1462 static int usb_host_scan_sys(void *opaque
, USBScanFunc
*func
)
1466 int bus_num
, addr
, speed
, class_id
, product_id
, vendor_id
;
1468 char port
[MAX_PORTLEN
];
1469 char product_name
[512];
1472 dir
= opendir(USBSYSBUS_PATH
"/devices");
1474 perror("husb: cannot open devices directory");
1478 while ((de
= readdir(dir
))) {
1479 if (de
->d_name
[0] != '.' && !strchr(de
->d_name
, ':')) {
1480 if (sscanf(de
->d_name
, "%d-%7[0-9.]", &bus_num
, port
) < 2) {
1484 if (!usb_host_read_file(line
, sizeof(line
), "devnum", de
->d_name
)) {
1487 if (sscanf(line
, "%d", &addr
) != 1) {
1490 if (!usb_host_read_file(line
, sizeof(line
), "bDeviceClass",
1494 if (sscanf(line
, "%x", &class_id
) != 1) {
1498 if (!usb_host_read_file(line
, sizeof(line
), "idVendor",
1502 if (sscanf(line
, "%x", &vendor_id
) != 1) {
1505 if (!usb_host_read_file(line
, sizeof(line
), "idProduct",
1509 if (sscanf(line
, "%x", &product_id
) != 1) {
1512 if (!usb_host_read_file(line
, sizeof(line
), "product",
1516 if (strlen(line
) > 0) {
1517 line
[strlen(line
) - 1] = '\0';
1519 pstrcpy(product_name
, sizeof(product_name
), line
);
1522 if (!usb_host_read_file(line
, sizeof(line
), "speed", de
->d_name
)) {
1525 if (!strcmp(line
, "480\n")) {
1526 speed
= USB_SPEED_HIGH
;
1527 } else if (!strcmp(line
, "1.5\n")) {
1528 speed
= USB_SPEED_LOW
;
1530 speed
= USB_SPEED_FULL
;
1533 ret
= func(opaque
, bus_num
, addr
, port
, class_id
, vendor_id
,
1534 product_id
, product_name
, speed
);
1548 * Determine how to access the host's USB devices and call the
1549 * specific support function.
1551 static int usb_host_scan(void *opaque
, USBScanFunc
*func
)
1553 Monitor
*mon
= cur_mon
;
1557 const char *fs_type
[] = {"unknown", "proc", "dev", "sys"};
1558 char devpath
[PATH_MAX
];
1560 /* only check the host once */
1562 dir
= opendir(USBSYSBUS_PATH
"/devices");
1564 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1565 strcpy(devpath
, USBDEVBUS_PATH
);
1566 usb_fs_type
= USB_FS_SYS
;
1568 DPRINTF(USBDBG_DEVOPENED
, USBSYSBUS_PATH
);
1571 f
= fopen(USBPROCBUS_PATH
"/devices", "r");
1573 /* devices found in /proc/bus/usb/ */
1574 strcpy(devpath
, USBPROCBUS_PATH
);
1575 usb_fs_type
= USB_FS_PROC
;
1577 DPRINTF(USBDBG_DEVOPENED
, USBPROCBUS_PATH
);
1580 /* try additional methods if an access method hasn't been found yet */
1581 f
= fopen(USBDEVBUS_PATH
"/devices", "r");
1583 /* devices found in /dev/bus/usb/ */
1584 strcpy(devpath
, USBDEVBUS_PATH
);
1585 usb_fs_type
= USB_FS_DEV
;
1587 DPRINTF(USBDBG_DEVOPENED
, USBDEVBUS_PATH
);
1593 monitor_printf(mon
, "husb: unable to access USB devices\n");
1598 /* the module setting (used later for opening devices) */
1599 usb_host_device_path
= qemu_mallocz(strlen(devpath
)+1);
1600 strcpy(usb_host_device_path
, devpath
);
1602 monitor_printf(mon
, "husb: using %s file-system with %s\n",
1603 fs_type
[usb_fs_type
], usb_host_device_path
);
1607 switch (usb_fs_type
) {
1610 ret
= usb_host_scan_dev(opaque
, func
);
1613 ret
= usb_host_scan_sys(opaque
, func
);
1622 static QEMUTimer
*usb_auto_timer
;
1624 static int usb_host_auto_scan(void *opaque
, int bus_num
, int addr
, char *port
,
1625 int class_id
, int vendor_id
, int product_id
,
1626 const char *product_name
, int speed
)
1628 struct USBAutoFilter
*f
;
1629 struct USBHostDevice
*s
;
1635 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1638 if (f
->bus_num
> 0 && f
->bus_num
!= bus_num
) {
1641 if (f
->addr
> 0 && f
->addr
!= addr
) {
1644 if (f
->port
!= NULL
&& (port
== NULL
|| strcmp(f
->port
, port
) != 0)) {
1648 if (f
->vendor_id
> 0 && f
->vendor_id
!= vendor_id
) {
1652 if (f
->product_id
> 0 && f
->product_id
!= product_id
) {
1655 /* We got a match */
1657 /* Already attached ? */
1661 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num
, addr
);
1663 usb_host_open(s
, bus_num
, addr
, port
, product_name
, speed
);
1669 static void usb_host_auto_check(void *unused
)
1671 struct USBHostDevice
*s
;
1672 int unconnected
= 0;
1674 usb_host_scan(NULL
, usb_host_auto_scan
);
1676 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1682 if (unconnected
== 0) {
1683 /* nothing to watch */
1684 if (usb_auto_timer
) {
1685 qemu_del_timer(usb_auto_timer
);
1690 if (!usb_auto_timer
) {
1691 usb_auto_timer
= qemu_new_timer_ms(rt_clock
, usb_host_auto_check
, NULL
);
1692 if (!usb_auto_timer
) {
1696 qemu_mod_timer(usb_auto_timer
, qemu_get_clock_ms(rt_clock
) + 2000);
1700 * Autoconnect filter
1702 * auto:bus:dev[:vid:pid]
1703 * auto:bus.dev[:vid:pid]
1705 * bus - bus number (dec, * means any)
1706 * dev - device number (dec, * means any)
1707 * vid - vendor id (hex, * means any)
1708 * pid - product id (hex, * means any)
1710 * See 'lsusb' output.
1712 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
)
1714 enum { BUS
, DEV
, VID
, PID
, DONE
};
1715 const char *p
= spec
;
1723 for (i
= BUS
; i
< DONE
; i
++) {
1724 p
= strpbrk(p
, ":.");
1734 case BUS
: f
->bus_num
= strtol(p
, NULL
, 10); break;
1735 case DEV
: f
->addr
= strtol(p
, NULL
, 10); break;
1736 case VID
: f
->vendor_id
= strtol(p
, NULL
, 16); break;
1737 case PID
: f
->product_id
= strtol(p
, NULL
, 16); break;
1742 fprintf(stderr
, "husb: invalid auto filter spec %s\n", spec
);
1749 /**********************/
1750 /* USB host device info */
1752 struct usb_class_info
{
1754 const char *class_name
;
1757 static const struct usb_class_info usb_class_info
[] = {
1758 { USB_CLASS_AUDIO
, "Audio"},
1759 { USB_CLASS_COMM
, "Communication"},
1760 { USB_CLASS_HID
, "HID"},
1761 { USB_CLASS_HUB
, "Hub" },
1762 { USB_CLASS_PHYSICAL
, "Physical" },
1763 { USB_CLASS_PRINTER
, "Printer" },
1764 { USB_CLASS_MASS_STORAGE
, "Storage" },
1765 { USB_CLASS_CDC_DATA
, "Data" },
1766 { USB_CLASS_APP_SPEC
, "Application Specific" },
1767 { USB_CLASS_VENDOR_SPEC
, "Vendor Specific" },
1768 { USB_CLASS_STILL_IMAGE
, "Still Image" },
1769 { USB_CLASS_CSCID
, "Smart Card" },
1770 { USB_CLASS_CONTENT_SEC
, "Content Security" },
1774 static const char *usb_class_str(uint8_t class)
1776 const struct usb_class_info
*p
;
1777 for(p
= usb_class_info
; p
->class != -1; p
++) {
1778 if (p
->class == class) {
1782 return p
->class_name
;
1785 static void usb_info_device(Monitor
*mon
, int bus_num
, int addr
, char *port
,
1786 int class_id
, int vendor_id
, int product_id
,
1787 const char *product_name
,
1790 const char *class_str
, *speed_str
;
1796 case USB_SPEED_FULL
:
1799 case USB_SPEED_HIGH
:
1807 monitor_printf(mon
, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1808 bus_num
, addr
, port
, speed_str
);
1809 class_str
= usb_class_str(class_id
);
1811 monitor_printf(mon
, " %s:", class_str
);
1813 monitor_printf(mon
, " Class %02x:", class_id
);
1815 monitor_printf(mon
, " USB device %04x:%04x", vendor_id
, product_id
);
1816 if (product_name
[0] != '\0') {
1817 monitor_printf(mon
, ", %s", product_name
);
1819 monitor_printf(mon
, "\n");
1822 static int usb_host_info_device(void *opaque
, int bus_num
, int addr
,
1823 char *path
, int class_id
,
1824 int vendor_id
, int product_id
,
1825 const char *product_name
,
1828 Monitor
*mon
= opaque
;
1830 usb_info_device(mon
, bus_num
, addr
, path
, class_id
, vendor_id
, product_id
,
1831 product_name
, speed
);
1835 static void dec2str(int val
, char *str
, size_t size
)
1838 snprintf(str
, size
, "*");
1840 snprintf(str
, size
, "%d", val
);
1844 static void hex2str(int val
, char *str
, size_t size
)
1847 snprintf(str
, size
, "*");
1849 snprintf(str
, size
, "%04x", val
);
1853 void usb_host_info(Monitor
*mon
)
1855 struct USBAutoFilter
*f
;
1856 struct USBHostDevice
*s
;
1858 usb_host_scan(mon
, usb_host_info_device
);
1860 if (QTAILQ_EMPTY(&hostdevs
)) {
1864 monitor_printf(mon
, " Auto filters:\n");
1865 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1866 char bus
[10], addr
[10], vid
[10], pid
[10];
1868 dec2str(f
->bus_num
, bus
, sizeof(bus
));
1869 dec2str(f
->addr
, addr
, sizeof(addr
));
1870 hex2str(f
->vendor_id
, vid
, sizeof(vid
));
1871 hex2str(f
->product_id
, pid
, sizeof(pid
));
1872 monitor_printf(mon
, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1873 bus
, addr
, f
->port
? f
->port
: "*", vid
, pid
);