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>
42 #include <linux/usbdevice_fs.h>
43 #include <linux/version.h>
46 /* We redefine it to avoid version problems */
47 struct usb_ctrltransfer
{
57 typedef int USBScanFunc(void *opaque
, int bus_num
, int addr
, char *port
,
58 int class_id
, int vendor_id
, int product_id
,
59 const char *product_name
, int speed
);
64 #define DPRINTF printf
69 #define USBDBG_DEVOPENED "husb: opened %s/devices\n"
71 #define USBPROCBUS_PATH "/proc/bus/usb"
72 #define PRODUCT_NAME_SZ 32
73 #define MAX_ENDPOINTS 15
74 #define MAX_PORTLEN 16
75 #define USBDEVBUS_PATH "/dev/bus/usb"
76 #define USBSYSBUS_PATH "/sys/bus/usb"
78 static char *usb_host_device_path
;
85 static int usb_fs_type
;
87 /* endpoint association data */
88 #define ISO_FRAME_DESC_PER_URB 32
89 #define ISO_URB_COUNT 3
90 #define INVALID_EP_TYPE 255
92 /* devio.c limits single requests to 16k */
93 #define MAX_USBFS_BUFFER_SIZE 16384
95 typedef struct AsyncURB AsyncURB
;
107 struct USBAutoFilter
{
115 typedef struct USBHostDevice
{
126 struct endp_data endp_table
[MAX_ENDPOINTS
];
127 QLIST_HEAD(, AsyncURB
) aurbs
;
129 /* Host side address */
132 char port
[MAX_PORTLEN
];
133 struct USBAutoFilter match
;
135 QTAILQ_ENTRY(USBHostDevice
) next
;
138 static QTAILQ_HEAD(, USBHostDevice
) hostdevs
= QTAILQ_HEAD_INITIALIZER(hostdevs
);
140 static int usb_host_close(USBHostDevice
*dev
);
141 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
);
142 static void usb_host_auto_check(void *unused
);
143 static int usb_host_read_file(char *line
, size_t line_size
,
144 const char *device_file
, const char *device_name
);
146 static int is_isoc(USBHostDevice
*s
, int ep
)
148 return s
->endp_table
[ep
- 1].type
== USBDEVFS_URB_TYPE_ISO
;
151 static int is_valid(USBHostDevice
*s
, int ep
)
153 return s
->endp_table
[ep
- 1].type
!= INVALID_EP_TYPE
;
156 static int is_halted(USBHostDevice
*s
, int ep
)
158 return s
->endp_table
[ep
- 1].halted
;
161 static void clear_halt(USBHostDevice
*s
, int ep
)
163 s
->endp_table
[ep
- 1].halted
= 0;
166 static void set_halt(USBHostDevice
*s
, int ep
)
168 s
->endp_table
[ep
- 1].halted
= 1;
171 static int is_iso_started(USBHostDevice
*s
, int ep
)
173 return s
->endp_table
[ep
- 1].iso_started
;
176 static void clear_iso_started(USBHostDevice
*s
, int ep
)
178 s
->endp_table
[ep
- 1].iso_started
= 0;
181 static void set_iso_started(USBHostDevice
*s
, int ep
)
183 s
->endp_table
[ep
- 1].iso_started
= 1;
186 static void set_iso_urb(USBHostDevice
*s
, int ep
, AsyncURB
*iso_urb
)
188 s
->endp_table
[ep
- 1].iso_urb
= iso_urb
;
191 static AsyncURB
*get_iso_urb(USBHostDevice
*s
, int ep
)
193 return s
->endp_table
[ep
- 1].iso_urb
;
196 static void set_iso_urb_idx(USBHostDevice
*s
, int ep
, int i
)
198 s
->endp_table
[ep
- 1].iso_urb_idx
= i
;
201 static int get_iso_urb_idx(USBHostDevice
*s
, int ep
)
203 return s
->endp_table
[ep
- 1].iso_urb_idx
;
206 static void set_iso_buffer_used(USBHostDevice
*s
, int ep
, int i
)
208 s
->endp_table
[ep
- 1].iso_buffer_used
= i
;
211 static int get_iso_buffer_used(USBHostDevice
*s
, int ep
)
213 return s
->endp_table
[ep
- 1].iso_buffer_used
;
216 static void set_max_packet_size(USBHostDevice
*s
, int ep
, uint8_t *descriptor
)
218 int raw
= descriptor
[4] + (descriptor
[5] << 8);
219 int size
, microframes
;
222 switch ((raw
>> 11) & 3) {
223 case 1: microframes
= 2; break;
224 case 2: microframes
= 3; break;
225 default: microframes
= 1; break;
227 DPRINTF("husb: max packet size: 0x%x -> %d x %d\n",
228 raw
, microframes
, size
);
229 s
->endp_table
[ep
- 1].max_packet_size
= size
* microframes
;
232 static int get_max_packet_size(USBHostDevice
*s
, int ep
)
234 return s
->endp_table
[ep
- 1].max_packet_size
;
239 * We always allocate iso packet descriptors even for bulk transfers
240 * to simplify allocation and casts.
244 struct usbdevfs_urb urb
;
245 struct usbdevfs_iso_packet_desc isocpd
[ISO_FRAME_DESC_PER_URB
];
247 QLIST_ENTRY(AsyncURB
) next
;
249 /* For regular async urbs */
251 int more
; /* large transfer, more urbs follow */
253 /* For buffered iso handling */
254 int iso_frame_idx
; /* -1 means in flight */
257 static AsyncURB
*async_alloc(USBHostDevice
*s
)
259 AsyncURB
*aurb
= qemu_mallocz(sizeof(AsyncURB
));
261 QLIST_INSERT_HEAD(&s
->aurbs
, aurb
, next
);
265 static void async_free(AsyncURB
*aurb
)
267 QLIST_REMOVE(aurb
, next
);
271 static void async_complete(void *opaque
)
273 USBHostDevice
*s
= opaque
;
279 int r
= ioctl(s
->fd
, USBDEVFS_REAPURBNDELAY
, &aurb
);
281 if (errno
== EAGAIN
) {
284 if (errno
== ENODEV
&& !s
->closing
) {
285 printf("husb: device %d.%d disconnected\n",
286 s
->bus_num
, s
->addr
);
288 usb_host_auto_check(NULL
);
292 DPRINTF("husb: async. reap urb failed errno %d\n", errno
);
296 DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
297 aurb
, aurb
->urb
.status
, aurb
->urb
.actual_length
);
299 /* If this is a buffered iso urb mark it as complete and don't do
300 anything else (it is handled further in usb_host_handle_iso_data) */
301 if (aurb
->iso_frame_idx
== -1) {
302 if (aurb
->urb
.status
== -EPIPE
) {
303 set_halt(s
, aurb
->urb
.endpoint
& 0xf);
305 aurb
->iso_frame_idx
= 0;
312 switch (aurb
->urb
.status
) {
314 p
->len
+= aurb
->urb
.actual_length
;
318 set_halt(s
, p
->devep
);
319 p
->len
= USB_RET_STALL
;
323 p
->len
= USB_RET_NAK
;
327 if (aurb
->urb
.type
== USBDEVFS_URB_TYPE_CONTROL
) {
328 usb_generic_async_ctrl_complete(&s
->dev
, p
);
329 } else if (!aurb
->more
) {
330 usb_packet_complete(&s
->dev
, p
);
338 static void usb_host_async_cancel(USBDevice
*dev
, USBPacket
*p
)
340 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
343 QLIST_FOREACH(aurb
, &s
->aurbs
, next
) {
344 if (p
!= aurb
->packet
) {
348 DPRINTF("husb: async cancel: packet %p, aurb %p\n", p
, aurb
);
350 /* Mark it as dead (see async_complete above) */
353 int r
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, aurb
);
355 DPRINTF("husb: async. discard urb failed errno %d\n", errno
);
360 static int usb_host_claim_interfaces(USBHostDevice
*dev
, int configuration
)
362 int dev_descr_len
, config_descr_len
;
363 int interface
, nb_interfaces
;
366 if (configuration
== 0) /* address state - ignore */
369 DPRINTF("husb: claiming interfaces. config %d\n", configuration
);
372 dev_descr_len
= dev
->descr
[0];
373 if (dev_descr_len
> dev
->descr_len
) {
378 while (i
< dev
->descr_len
) {
379 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
381 dev
->descr
[i
], dev
->descr
[i
+1]);
383 if (dev
->descr
[i
+1] != USB_DT_CONFIG
) {
387 config_descr_len
= dev
->descr
[i
];
389 printf("husb: config #%d need %d\n", dev
->descr
[i
+ 5], configuration
);
391 if (configuration
< 0 || configuration
== dev
->descr
[i
+ 5]) {
392 configuration
= dev
->descr
[i
+ 5];
396 i
+= config_descr_len
;
399 if (i
>= dev
->descr_len
) {
401 "husb: update iface failed. no matching configuration\n");
404 nb_interfaces
= dev
->descr
[i
+ 4];
406 #ifdef USBDEVFS_DISCONNECT
407 /* earlier Linux 2.4 do not support that */
409 struct usbdevfs_ioctl ctrl
;
410 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
411 ctrl
.ioctl_code
= USBDEVFS_DISCONNECT
;
412 ctrl
.ifno
= interface
;
414 ret
= ioctl(dev
->fd
, USBDEVFS_IOCTL
, &ctrl
);
415 if (ret
< 0 && errno
!= ENODATA
) {
416 perror("USBDEVFS_DISCONNECT");
423 /* XXX: only grab if all interfaces are free */
424 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
425 ret
= ioctl(dev
->fd
, USBDEVFS_CLAIMINTERFACE
, &interface
);
427 if (errno
== EBUSY
) {
428 printf("husb: update iface. device already grabbed\n");
430 perror("husb: failed to claim interface");
437 printf("husb: %d interfaces claimed for configuration %d\n",
438 nb_interfaces
, configuration
);
440 dev
->ninterfaces
= nb_interfaces
;
441 dev
->configuration
= configuration
;
445 static int usb_host_release_interfaces(USBHostDevice
*s
)
449 DPRINTF("husb: releasing interfaces\n");
451 for (i
= 0; i
< s
->ninterfaces
; i
++) {
452 ret
= ioctl(s
->fd
, USBDEVFS_RELEASEINTERFACE
, &i
);
454 perror("husb: failed to release interface");
462 static void usb_host_handle_reset(USBDevice
*dev
)
464 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
466 DPRINTF("husb: reset device %u.%u\n", s
->bus_num
, s
->addr
);
468 ioctl(s
->fd
, USBDEVFS_RESET
);
470 usb_host_claim_interfaces(s
, s
->configuration
);
473 static void usb_host_handle_destroy(USBDevice
*dev
)
475 USBHostDevice
*s
= (USBHostDevice
*)dev
;
478 QTAILQ_REMOVE(&hostdevs
, s
, next
);
479 qemu_remove_exit_notifier(&s
->exit
);
482 static int usb_linux_update_endp_table(USBHostDevice
*s
);
484 /* iso data is special, we need to keep enough urbs in flight to make sure
485 that the controller never runs out of them, otherwise the device will
486 likely suffer a buffer underrun / overrun. */
487 static AsyncURB
*usb_host_alloc_iso(USBHostDevice
*s
, uint8_t ep
, int in
)
490 int i
, j
, len
= get_max_packet_size(s
, ep
);
492 aurb
= qemu_mallocz(ISO_URB_COUNT
* sizeof(*aurb
));
493 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
494 aurb
[i
].urb
.endpoint
= ep
;
495 aurb
[i
].urb
.buffer_length
= ISO_FRAME_DESC_PER_URB
* len
;
496 aurb
[i
].urb
.buffer
= qemu_malloc(aurb
[i
].urb
.buffer_length
);
497 aurb
[i
].urb
.type
= USBDEVFS_URB_TYPE_ISO
;
498 aurb
[i
].urb
.flags
= USBDEVFS_URB_ISO_ASAP
;
499 aurb
[i
].urb
.number_of_packets
= ISO_FRAME_DESC_PER_URB
;
500 for (j
= 0 ; j
< ISO_FRAME_DESC_PER_URB
; j
++)
501 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
503 aurb
[i
].urb
.endpoint
|= 0x80;
504 /* Mark as fully consumed (idle) */
505 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
;
508 set_iso_urb(s
, ep
, aurb
);
513 static void usb_host_stop_n_free_iso(USBHostDevice
*s
, uint8_t ep
)
516 int i
, ret
, killed
= 0, free
= 1;
518 aurb
= get_iso_urb(s
, ep
);
523 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
525 if (aurb
[i
].iso_frame_idx
== -1) {
526 ret
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, &aurb
[i
]);
528 printf("husb: discard isoc in urb failed errno %d\n", errno
);
536 /* Make sure any urbs we've killed are reaped before we free them */
541 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
542 qemu_free(aurb
[i
].urb
.buffer
);
548 printf("husb: leaking iso urbs because of discard failure\n");
549 set_iso_urb(s
, ep
, NULL
);
550 set_iso_urb_idx(s
, ep
, 0);
551 clear_iso_started(s
, ep
);
554 static int urb_status_to_usb_ret(int status
)
558 return USB_RET_STALL
;
564 static int usb_host_handle_iso_data(USBHostDevice
*s
, USBPacket
*p
, int in
)
567 int i
, j
, ret
, max_packet_size
, offset
, len
= 0;
569 max_packet_size
= get_max_packet_size(s
, p
->devep
);
570 if (max_packet_size
== 0)
573 aurb
= get_iso_urb(s
, p
->devep
);
575 aurb
= usb_host_alloc_iso(s
, p
->devep
, in
);
578 i
= get_iso_urb_idx(s
, p
->devep
);
579 j
= aurb
[i
].iso_frame_idx
;
580 if (j
>= 0 && j
< ISO_FRAME_DESC_PER_URB
) {
582 /* Check urb status */
583 if (aurb
[i
].urb
.status
) {
584 len
= urb_status_to_usb_ret(aurb
[i
].urb
.status
);
585 /* Move to the next urb */
586 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
- 1;
587 /* Check frame status */
588 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].status
) {
589 len
= urb_status_to_usb_ret(
590 aurb
[i
].urb
.iso_frame_desc
[j
].status
);
591 /* Check the frame fits */
592 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
> p
->len
) {
593 printf("husb: received iso data is larger then packet\n");
595 /* All good copy data over */
597 len
= aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
;
600 j
* aurb
[i
].urb
.iso_frame_desc
[0].length
,
605 offset
= (j
== 0) ? 0 : get_iso_buffer_used(s
, p
->devep
);
607 /* Check the frame fits */
608 if (len
> max_packet_size
) {
609 printf("husb: send iso data is larger then max packet size\n");
613 /* All good copy data over */
614 memcpy(aurb
[i
].urb
.buffer
+ offset
, p
->data
, len
);
615 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
617 set_iso_buffer_used(s
, p
->devep
, offset
);
619 /* Start the stream once we have buffered enough data */
620 if (!is_iso_started(s
, p
->devep
) && i
== 1 && j
== 8) {
621 set_iso_started(s
, p
->devep
);
624 aurb
[i
].iso_frame_idx
++;
625 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
626 i
= (i
+ 1) % ISO_URB_COUNT
;
627 set_iso_urb_idx(s
, p
->devep
, i
);
631 set_iso_started(s
, p
->devep
);
633 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
637 if (is_iso_started(s
, p
->devep
)) {
638 /* (Re)-submit all fully consumed / filled urbs */
639 for (i
= 0; i
< ISO_URB_COUNT
; i
++) {
640 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
641 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, &aurb
[i
]);
643 printf("husb error submitting iso urb %d: %d\n", i
, errno
);
644 if (!in
|| len
== 0) {
656 aurb
[i
].iso_frame_idx
= -1;
664 static int usb_host_handle_data(USBDevice
*dev
, USBPacket
*p
)
666 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
667 struct usbdevfs_urb
*urb
;
673 if (!is_valid(s
, p
->devep
)) {
677 if (p
->pid
== USB_TOKEN_IN
) {
678 ep
= p
->devep
| 0x80;
683 if (is_halted(s
, p
->devep
)) {
684 ret
= ioctl(s
->fd
, USBDEVFS_CLEAR_HALT
, &ep
);
686 DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
690 clear_halt(s
, p
->devep
);
693 if (is_isoc(s
, p
->devep
)) {
694 return usb_host_handle_iso_data(s
, p
, p
->pid
== USB_TOKEN_IN
);
701 aurb
= async_alloc(s
);
706 urb
->type
= USBDEVFS_URB_TYPE_BULK
;
707 urb
->usercontext
= s
;
710 if (rem
> MAX_USBFS_BUFFER_SIZE
) {
711 urb
->buffer_length
= MAX_USBFS_BUFFER_SIZE
;
714 urb
->buffer_length
= rem
;
717 pbuf
+= urb
->buffer_length
;
718 rem
-= urb
->buffer_length
;
720 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
722 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
723 urb
->endpoint
, urb
->buffer_length
, aurb
->more
, p
, aurb
);
726 DPRINTF("husb: submit failed. errno %d\n", errno
);
734 return USB_RET_STALL
;
739 return USB_RET_ASYNC
;
742 static int ctrl_error(void)
744 if (errno
== ETIMEDOUT
) {
747 return USB_RET_STALL
;
751 static int usb_host_set_address(USBHostDevice
*s
, int addr
)
753 DPRINTF("husb: ctrl set addr %u\n", addr
);
758 static int usb_host_set_config(USBHostDevice
*s
, int config
)
760 usb_host_release_interfaces(s
);
762 int ret
= ioctl(s
->fd
, USBDEVFS_SETCONFIGURATION
, &config
);
764 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config
, ret
, errno
);
769 usb_host_claim_interfaces(s
, config
);
773 static int usb_host_set_interface(USBHostDevice
*s
, int iface
, int alt
)
775 struct usbdevfs_setinterface si
;
778 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
780 usb_host_stop_n_free_iso(s
, i
);
784 si
.interface
= iface
;
786 ret
= ioctl(s
->fd
, USBDEVFS_SETINTERFACE
, &si
);
788 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
789 iface
, alt
, ret
, errno
);
794 usb_linux_update_endp_table(s
);
798 static int usb_host_handle_control(USBDevice
*dev
, USBPacket
*p
,
799 int request
, int value
, int index
, int length
, uint8_t *data
)
801 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
802 struct usbdevfs_urb
*urb
;
807 * Process certain standard device requests.
808 * These are infrequent and are processed synchronously.
811 /* Note request is (bRequestType << 8) | bRequest */
812 DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
813 request
>> 8, request
& 0xff, value
, index
, length
);
816 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
817 return usb_host_set_address(s
, value
);
819 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
820 return usb_host_set_config(s
, value
& 0xff);
822 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
823 return usb_host_set_interface(s
, index
, value
);
826 /* The rest are asynchronous */
828 if (length
> sizeof(dev
->data_buf
)) {
829 fprintf(stderr
, "husb: ctrl buffer too small (%d > %zu)\n",
830 length
, sizeof(dev
->data_buf
));
831 return USB_RET_STALL
;
834 aurb
= async_alloc(s
);
838 * Setup ctrl transfer.
840 * s->ctrl is laid out such that data buffer immediately follows
841 * 'req' struct which is exactly what usbdevfs expects.
845 urb
->type
= USBDEVFS_URB_TYPE_CONTROL
;
846 urb
->endpoint
= p
->devep
;
848 urb
->buffer
= &dev
->setup_buf
;
849 urb
->buffer_length
= length
+ 8;
851 urb
->usercontext
= s
;
853 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
855 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb
->buffer_length
, aurb
);
858 DPRINTF("husb: submit failed. errno %d\n", errno
);
866 return USB_RET_STALL
;
870 return USB_RET_ASYNC
;
873 static int usb_linux_get_configuration(USBHostDevice
*s
)
875 uint8_t configuration
;
876 struct usb_ctrltransfer ct
;
879 if (usb_fs_type
== USB_FS_SYS
) {
880 char device_name
[32], line
[1024];
883 sprintf(device_name
, "%d-%s", s
->bus_num
, s
->port
);
885 if (!usb_host_read_file(line
, sizeof(line
), "bConfigurationValue",
889 if (sscanf(line
, "%d", &configuration
) != 1) {
892 return configuration
;
896 ct
.bRequestType
= USB_DIR_IN
;
897 ct
.bRequest
= USB_REQ_GET_CONFIGURATION
;
901 ct
.data
= &configuration
;
904 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
906 perror("usb_linux_get_configuration");
910 /* in address state */
911 if (configuration
== 0) {
915 return configuration
;
918 static uint8_t usb_linux_get_alt_setting(USBHostDevice
*s
,
919 uint8_t configuration
, uint8_t interface
)
922 struct usb_ctrltransfer ct
;
925 if (usb_fs_type
== USB_FS_SYS
) {
926 char device_name
[64], line
[1024];
929 sprintf(device_name
, "%d-%s:%d.%d", s
->bus_num
, s
->port
,
930 (int)configuration
, (int)interface
);
932 if (!usb_host_read_file(line
, sizeof(line
), "bAlternateSetting",
936 if (sscanf(line
, "%d", &alt_setting
) != 1) {
943 ct
.bRequestType
= USB_DIR_IN
| USB_RECIP_INTERFACE
;
944 ct
.bRequest
= USB_REQ_GET_INTERFACE
;
946 ct
.wIndex
= interface
;
948 ct
.data
= &alt_setting
;
950 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
952 /* Assume alt 0 on error */
959 /* returns 1 on problem encountered or 0 for success */
960 static int usb_linux_update_endp_table(USBHostDevice
*s
)
962 uint8_t *descriptors
;
963 uint8_t devep
, type
, configuration
, alt_interface
;
964 int interface
, length
, i
;
966 for (i
= 0; i
< MAX_ENDPOINTS
; i
++)
967 s
->endp_table
[i
].type
= INVALID_EP_TYPE
;
969 i
= usb_linux_get_configuration(s
);
974 /* get the desired configuration, interface, and endpoint descriptors
975 * from device description */
976 descriptors
= &s
->descr
[18];
977 length
= s
->descr_len
- 18;
980 if (descriptors
[i
+ 1] != USB_DT_CONFIG
||
981 descriptors
[i
+ 5] != configuration
) {
982 DPRINTF("invalid descriptor data - configuration\n");
988 if (descriptors
[i
+ 1] != USB_DT_INTERFACE
||
989 (descriptors
[i
+ 1] == USB_DT_INTERFACE
&&
990 descriptors
[i
+ 4] == 0)) {
995 interface
= descriptors
[i
+ 2];
996 alt_interface
= usb_linux_get_alt_setting(s
, configuration
, interface
);
998 /* the current interface descriptor is the active interface
999 * and has endpoints */
1000 if (descriptors
[i
+ 3] != alt_interface
) {
1001 i
+= descriptors
[i
];
1005 /* advance to the endpoints */
1006 while (i
< length
&& descriptors
[i
+1] != USB_DT_ENDPOINT
) {
1007 i
+= descriptors
[i
];
1013 while (i
< length
) {
1014 if (descriptors
[i
+ 1] != USB_DT_ENDPOINT
) {
1018 devep
= descriptors
[i
+ 2];
1019 switch (descriptors
[i
+ 3] & 0x3) {
1021 type
= USBDEVFS_URB_TYPE_CONTROL
;
1024 type
= USBDEVFS_URB_TYPE_ISO
;
1025 set_max_packet_size(s
, (devep
& 0xf), descriptors
+ i
);
1028 type
= USBDEVFS_URB_TYPE_BULK
;
1031 type
= USBDEVFS_URB_TYPE_INTERRUPT
;
1034 DPRINTF("usb_host: malformed endpoint type\n");
1035 type
= USBDEVFS_URB_TYPE_BULK
;
1037 s
->endp_table
[(devep
& 0xf) - 1].type
= type
;
1038 s
->endp_table
[(devep
& 0xf) - 1].halted
= 0;
1040 i
+= descriptors
[i
];
1046 static int usb_host_open(USBHostDevice
*dev
, int bus_num
,
1047 int addr
, char *port
, const char *prod_name
)
1050 struct usbdevfs_connectinfo ci
;
1053 if (dev
->fd
!= -1) {
1056 printf("husb: open device %d.%d\n", bus_num
, addr
);
1058 if (!usb_host_device_path
) {
1059 perror("husb: USB Host Device Path not set");
1062 snprintf(buf
, sizeof(buf
), "%s/%03d/%03d", usb_host_device_path
,
1064 fd
= open(buf
, O_RDWR
| O_NONBLOCK
);
1069 DPRINTF("husb: opened %s\n", buf
);
1071 dev
->bus_num
= bus_num
;
1073 strcpy(dev
->port
, port
);
1076 /* read the device description */
1077 dev
->descr_len
= read(fd
, dev
->descr
, sizeof(dev
->descr
));
1078 if (dev
->descr_len
<= 0) {
1079 perror("husb: reading device data failed");
1086 printf("=== begin dumping device descriptor data ===\n");
1087 for (x
= 0; x
< dev
->descr_len
; x
++) {
1088 printf("%02x ", dev
->descr
[x
]);
1090 printf("\n=== end dumping device descriptor data ===\n");
1096 * Initial configuration is -1 which makes us claim first
1097 * available config. We used to start with 1, which does not
1098 * always work. I've seen devices where first config starts
1101 if (!usb_host_claim_interfaces(dev
, -1)) {
1105 ret
= ioctl(fd
, USBDEVFS_CONNECTINFO
, &ci
);
1107 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1111 printf("husb: grabbed usb device %d.%d\n", bus_num
, addr
);
1113 ret
= usb_linux_update_endp_table(dev
);
1119 dev
->dev
.speed
= USB_SPEED_LOW
;
1121 dev
->dev
.speed
= USB_SPEED_HIGH
;
1124 if (!prod_name
|| prod_name
[0] == '\0') {
1125 snprintf(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1126 "host:%d.%d", bus_num
, addr
);
1128 pstrcpy(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1132 /* USB devio uses 'write' flag to check for async completions */
1133 qemu_set_fd_handler(dev
->fd
, NULL
, async_complete
, dev
);
1135 usb_device_attach(&dev
->dev
);
1146 static int usb_host_close(USBHostDevice
*dev
)
1150 if (dev
->fd
== -1) {
1154 qemu_set_fd_handler(dev
->fd
, NULL
, NULL
, NULL
);
1156 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
1157 if (is_isoc(dev
, i
)) {
1158 usb_host_stop_n_free_iso(dev
, i
);
1161 async_complete(dev
);
1163 usb_device_detach(&dev
->dev
);
1164 ioctl(dev
->fd
, USBDEVFS_RESET
);
1170 static void usb_host_exit_notifier(struct Notifier
* n
)
1172 USBHostDevice
*s
= container_of(n
, USBHostDevice
, exit
);
1175 ioctl(s
->fd
, USBDEVFS_RESET
);
1179 static int usb_host_initfn(USBDevice
*dev
)
1181 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
1183 dev
->auto_attach
= 0;
1185 QTAILQ_INSERT_TAIL(&hostdevs
, s
, next
);
1186 s
->exit
.notify
= usb_host_exit_notifier
;
1187 qemu_add_exit_notifier(&s
->exit
);
1188 usb_host_auto_check(NULL
);
1192 static struct USBDeviceInfo usb_host_dev_info
= {
1193 .product_desc
= "USB Host Device",
1194 .qdev
.name
= "usb-host",
1195 .qdev
.size
= sizeof(USBHostDevice
),
1196 .init
= usb_host_initfn
,
1197 .handle_packet
= usb_generic_handle_packet
,
1198 .cancel_packet
= usb_host_async_cancel
,
1199 .handle_data
= usb_host_handle_data
,
1200 .handle_control
= usb_host_handle_control
,
1201 .handle_reset
= usb_host_handle_reset
,
1202 .handle_destroy
= usb_host_handle_destroy
,
1203 .usbdevice_name
= "host",
1204 .usbdevice_init
= usb_host_device_open
,
1205 .qdev
.props
= (Property
[]) {
1206 DEFINE_PROP_UINT32("hostbus", USBHostDevice
, match
.bus_num
, 0),
1207 DEFINE_PROP_UINT32("hostaddr", USBHostDevice
, match
.addr
, 0),
1208 DEFINE_PROP_STRING("hostport", USBHostDevice
, match
.port
),
1209 DEFINE_PROP_HEX32("vendorid", USBHostDevice
, match
.vendor_id
, 0),
1210 DEFINE_PROP_HEX32("productid", USBHostDevice
, match
.product_id
, 0),
1211 DEFINE_PROP_END_OF_LIST(),
1215 static void usb_host_register_devices(void)
1217 usb_qdev_register(&usb_host_dev_info
);
1219 device_init(usb_host_register_devices
)
1221 USBDevice
*usb_host_device_open(const char *devname
)
1223 struct USBAutoFilter filter
;
1227 dev
= usb_create(NULL
/* FIXME */, "usb-host");
1229 if (strstr(devname
, "auto:")) {
1230 if (parse_filter(devname
, &filter
) < 0) {
1234 if ((p
= strchr(devname
, '.'))) {
1235 filter
.bus_num
= strtoul(devname
, NULL
, 0);
1236 filter
.addr
= strtoul(p
+ 1, NULL
, 0);
1237 filter
.vendor_id
= 0;
1238 filter
.product_id
= 0;
1239 } else if ((p
= strchr(devname
, ':'))) {
1242 filter
.vendor_id
= strtoul(devname
, NULL
, 16);
1243 filter
.product_id
= strtoul(p
+ 1, NULL
, 16);
1249 qdev_prop_set_uint32(&dev
->qdev
, "hostbus", filter
.bus_num
);
1250 qdev_prop_set_uint32(&dev
->qdev
, "hostaddr", filter
.addr
);
1251 qdev_prop_set_uint32(&dev
->qdev
, "vendorid", filter
.vendor_id
);
1252 qdev_prop_set_uint32(&dev
->qdev
, "productid", filter
.product_id
);
1253 qdev_init_nofail(&dev
->qdev
);
1257 qdev_free(&dev
->qdev
);
1261 int usb_host_device_close(const char *devname
)
1264 char product_name
[PRODUCT_NAME_SZ
];
1268 if (strstr(devname
, "auto:")) {
1269 return usb_host_auto_del(devname
);
1271 if (usb_host_find_device(&bus_num
, &addr
, product_name
,
1272 sizeof(product_name
), devname
) < 0) {
1275 s
= hostdev_find(bus_num
, addr
);
1277 usb_device_delete_addr(s
->bus_num
, s
->dev
.addr
);
1285 static int get_tag_value(char *buf
, int buf_size
,
1286 const char *str
, const char *tag
,
1287 const char *stopchars
)
1291 p
= strstr(str
, tag
);
1296 while (qemu_isspace(*p
)) {
1300 while (*p
!= '\0' && !strchr(stopchars
, *p
)) {
1301 if ((q
- buf
) < (buf_size
- 1)) {
1311 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1312 * host's USB devices. This is legacy support since many distributions
1313 * are moving to /sys/bus/usb
1315 static int usb_host_scan_dev(void *opaque
, USBScanFunc
*func
)
1320 int bus_num
, addr
, speed
, device_count
, class_id
, product_id
, vendor_id
;
1321 char product_name
[512];
1324 if (!usb_host_device_path
) {
1325 perror("husb: USB Host Device Path not set");
1328 snprintf(line
, sizeof(line
), "%s/devices", usb_host_device_path
);
1329 f
= fopen(line
, "r");
1331 perror("husb: cannot open devices file");
1336 bus_num
= addr
= speed
= class_id
= product_id
= vendor_id
= 0;
1338 if (fgets(line
, sizeof(line
), f
) == NULL
) {
1341 if (strlen(line
) > 0) {
1342 line
[strlen(line
) - 1] = '\0';
1344 if (line
[0] == 'T' && line
[1] == ':') {
1345 if (device_count
&& (vendor_id
|| product_id
)) {
1346 /* New device. Add the previously discovered device. */
1347 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1348 product_id
, product_name
, speed
);
1353 if (get_tag_value(buf
, sizeof(buf
), line
, "Bus=", " ") < 0) {
1356 bus_num
= atoi(buf
);
1357 if (get_tag_value(buf
, sizeof(buf
), line
, "Dev#=", " ") < 0) {
1361 if (get_tag_value(buf
, sizeof(buf
), line
, "Spd=", " ") < 0) {
1364 if (!strcmp(buf
, "480")) {
1365 speed
= USB_SPEED_HIGH
;
1366 } else if (!strcmp(buf
, "1.5")) {
1367 speed
= USB_SPEED_LOW
;
1369 speed
= USB_SPEED_FULL
;
1371 product_name
[0] = '\0';
1376 } else if (line
[0] == 'P' && line
[1] == ':') {
1377 if (get_tag_value(buf
, sizeof(buf
), line
, "Vendor=", " ") < 0) {
1380 vendor_id
= strtoul(buf
, NULL
, 16);
1381 if (get_tag_value(buf
, sizeof(buf
), line
, "ProdID=", " ") < 0) {
1384 product_id
= strtoul(buf
, NULL
, 16);
1385 } else if (line
[0] == 'S' && line
[1] == ':') {
1386 if (get_tag_value(buf
, sizeof(buf
), line
, "Product=", "") < 0) {
1389 pstrcpy(product_name
, sizeof(product_name
), buf
);
1390 } else if (line
[0] == 'D' && line
[1] == ':') {
1391 if (get_tag_value(buf
, sizeof(buf
), line
, "Cls=", " (") < 0) {
1394 class_id
= strtoul(buf
, NULL
, 16);
1398 if (device_count
&& (vendor_id
|| product_id
)) {
1399 /* Add the last device. */
1400 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1401 product_id
, product_name
, speed
);
1411 * Read sys file-system device file
1413 * @line address of buffer to put file contents in
1414 * @line_size size of line
1415 * @device_file path to device file (printf format string)
1416 * @device_name device being opened (inserted into device_file)
1418 * @return 0 failed, 1 succeeded ('line' contains data)
1420 static int usb_host_read_file(char *line
, size_t line_size
,
1421 const char *device_file
, const char *device_name
)
1425 char filename
[PATH_MAX
];
1427 snprintf(filename
, PATH_MAX
, USBSYSBUS_PATH
"/devices/%s/%s", device_name
,
1429 f
= fopen(filename
, "r");
1431 ret
= fgets(line
, line_size
, f
) != NULL
;
1439 * Use /sys/bus/usb/devices/ directory to determine host's USB
1442 * This code is based on Robert Schiele's original patches posted to
1443 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1445 static int usb_host_scan_sys(void *opaque
, USBScanFunc
*func
)
1449 int bus_num
, addr
, speed
, class_id
, product_id
, vendor_id
;
1451 char port
[MAX_PORTLEN
];
1452 char product_name
[512];
1455 dir
= opendir(USBSYSBUS_PATH
"/devices");
1457 perror("husb: cannot open devices directory");
1461 while ((de
= readdir(dir
))) {
1462 if (de
->d_name
[0] != '.' && !strchr(de
->d_name
, ':')) {
1463 if (sscanf(de
->d_name
, "%d-%7[0-9.]", &bus_num
, port
) < 2) {
1467 if (!usb_host_read_file(line
, sizeof(line
), "devnum", de
->d_name
)) {
1470 if (sscanf(line
, "%d", &addr
) != 1) {
1473 if (!usb_host_read_file(line
, sizeof(line
), "bDeviceClass",
1477 if (sscanf(line
, "%x", &class_id
) != 1) {
1481 if (!usb_host_read_file(line
, sizeof(line
), "idVendor",
1485 if (sscanf(line
, "%x", &vendor_id
) != 1) {
1488 if (!usb_host_read_file(line
, sizeof(line
), "idProduct",
1492 if (sscanf(line
, "%x", &product_id
) != 1) {
1495 if (!usb_host_read_file(line
, sizeof(line
), "product",
1499 if (strlen(line
) > 0) {
1500 line
[strlen(line
) - 1] = '\0';
1502 pstrcpy(product_name
, sizeof(product_name
), line
);
1505 if (!usb_host_read_file(line
, sizeof(line
), "speed", de
->d_name
)) {
1508 if (!strcmp(line
, "480\n")) {
1509 speed
= USB_SPEED_HIGH
;
1510 } else if (!strcmp(line
, "1.5\n")) {
1511 speed
= USB_SPEED_LOW
;
1513 speed
= USB_SPEED_FULL
;
1516 ret
= func(opaque
, bus_num
, addr
, port
, class_id
, vendor_id
,
1517 product_id
, product_name
, speed
);
1531 * Determine how to access the host's USB devices and call the
1532 * specific support function.
1534 static int usb_host_scan(void *opaque
, USBScanFunc
*func
)
1536 Monitor
*mon
= cur_mon
;
1540 const char *fs_type
[] = {"unknown", "proc", "dev", "sys"};
1541 char devpath
[PATH_MAX
];
1543 /* only check the host once */
1545 dir
= opendir(USBSYSBUS_PATH
"/devices");
1547 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1548 strcpy(devpath
, USBDEVBUS_PATH
);
1549 usb_fs_type
= USB_FS_SYS
;
1551 DPRINTF(USBDBG_DEVOPENED
, USBSYSBUS_PATH
);
1554 f
= fopen(USBPROCBUS_PATH
"/devices", "r");
1556 /* devices found in /proc/bus/usb/ */
1557 strcpy(devpath
, USBPROCBUS_PATH
);
1558 usb_fs_type
= USB_FS_PROC
;
1560 DPRINTF(USBDBG_DEVOPENED
, USBPROCBUS_PATH
);
1563 /* try additional methods if an access method hasn't been found yet */
1564 f
= fopen(USBDEVBUS_PATH
"/devices", "r");
1566 /* devices found in /dev/bus/usb/ */
1567 strcpy(devpath
, USBDEVBUS_PATH
);
1568 usb_fs_type
= USB_FS_DEV
;
1570 DPRINTF(USBDBG_DEVOPENED
, USBDEVBUS_PATH
);
1576 monitor_printf(mon
, "husb: unable to access USB devices\n");
1581 /* the module setting (used later for opening devices) */
1582 usb_host_device_path
= qemu_mallocz(strlen(devpath
)+1);
1583 strcpy(usb_host_device_path
, devpath
);
1585 monitor_printf(mon
, "husb: using %s file-system with %s\n",
1586 fs_type
[usb_fs_type
], usb_host_device_path
);
1590 switch (usb_fs_type
) {
1593 ret
= usb_host_scan_dev(opaque
, func
);
1596 ret
= usb_host_scan_sys(opaque
, func
);
1605 static QEMUTimer
*usb_auto_timer
;
1607 static int usb_host_auto_scan(void *opaque
, int bus_num
, int addr
, char *port
,
1608 int class_id
, int vendor_id
, int product_id
,
1609 const char *product_name
, int speed
)
1611 struct USBAutoFilter
*f
;
1612 struct USBHostDevice
*s
;
1618 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1621 if (f
->bus_num
> 0 && f
->bus_num
!= bus_num
) {
1624 if (f
->addr
> 0 && f
->addr
!= addr
) {
1627 if (f
->port
!= NULL
&& (port
== NULL
|| strcmp(f
->port
, port
) != 0)) {
1631 if (f
->vendor_id
> 0 && f
->vendor_id
!= vendor_id
) {
1635 if (f
->product_id
> 0 && f
->product_id
!= product_id
) {
1638 /* We got a match */
1640 /* Already attached ? */
1644 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num
, addr
);
1646 usb_host_open(s
, bus_num
, addr
, port
, product_name
);
1652 static void usb_host_auto_check(void *unused
)
1654 struct USBHostDevice
*s
;
1655 int unconnected
= 0;
1657 usb_host_scan(NULL
, usb_host_auto_scan
);
1659 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1665 if (unconnected
== 0) {
1666 /* nothing to watch */
1667 if (usb_auto_timer
) {
1668 qemu_del_timer(usb_auto_timer
);
1673 if (!usb_auto_timer
) {
1674 usb_auto_timer
= qemu_new_timer_ms(rt_clock
, usb_host_auto_check
, NULL
);
1675 if (!usb_auto_timer
) {
1679 qemu_mod_timer(usb_auto_timer
, qemu_get_clock_ms(rt_clock
) + 2000);
1683 * Autoconnect filter
1685 * auto:bus:dev[:vid:pid]
1686 * auto:bus.dev[:vid:pid]
1688 * bus - bus number (dec, * means any)
1689 * dev - device number (dec, * means any)
1690 * vid - vendor id (hex, * means any)
1691 * pid - product id (hex, * means any)
1693 * See 'lsusb' output.
1695 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
)
1697 enum { BUS
, DEV
, VID
, PID
, DONE
};
1698 const char *p
= spec
;
1706 for (i
= BUS
; i
< DONE
; i
++) {
1707 p
= strpbrk(p
, ":.");
1717 case BUS
: f
->bus_num
= strtol(p
, NULL
, 10); break;
1718 case DEV
: f
->addr
= strtol(p
, NULL
, 10); break;
1719 case VID
: f
->vendor_id
= strtol(p
, NULL
, 16); break;
1720 case PID
: f
->product_id
= strtol(p
, NULL
, 16); break;
1725 fprintf(stderr
, "husb: invalid auto filter spec %s\n", spec
);
1732 /**********************/
1733 /* USB host device info */
1735 struct usb_class_info
{
1737 const char *class_name
;
1740 static const struct usb_class_info usb_class_info
[] = {
1741 { USB_CLASS_AUDIO
, "Audio"},
1742 { USB_CLASS_COMM
, "Communication"},
1743 { USB_CLASS_HID
, "HID"},
1744 { USB_CLASS_HUB
, "Hub" },
1745 { USB_CLASS_PHYSICAL
, "Physical" },
1746 { USB_CLASS_PRINTER
, "Printer" },
1747 { USB_CLASS_MASS_STORAGE
, "Storage" },
1748 { USB_CLASS_CDC_DATA
, "Data" },
1749 { USB_CLASS_APP_SPEC
, "Application Specific" },
1750 { USB_CLASS_VENDOR_SPEC
, "Vendor Specific" },
1751 { USB_CLASS_STILL_IMAGE
, "Still Image" },
1752 { USB_CLASS_CSCID
, "Smart Card" },
1753 { USB_CLASS_CONTENT_SEC
, "Content Security" },
1757 static const char *usb_class_str(uint8_t class)
1759 const struct usb_class_info
*p
;
1760 for(p
= usb_class_info
; p
->class != -1; p
++) {
1761 if (p
->class == class) {
1765 return p
->class_name
;
1768 static void usb_info_device(Monitor
*mon
, int bus_num
, int addr
, char *port
,
1769 int class_id
, int vendor_id
, int product_id
,
1770 const char *product_name
,
1773 const char *class_str
, *speed_str
;
1779 case USB_SPEED_FULL
:
1782 case USB_SPEED_HIGH
:
1790 monitor_printf(mon
, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1791 bus_num
, addr
, port
, speed_str
);
1792 class_str
= usb_class_str(class_id
);
1794 monitor_printf(mon
, " %s:", class_str
);
1796 monitor_printf(mon
, " Class %02x:", class_id
);
1798 monitor_printf(mon
, " USB device %04x:%04x", vendor_id
, product_id
);
1799 if (product_name
[0] != '\0') {
1800 monitor_printf(mon
, ", %s", product_name
);
1802 monitor_printf(mon
, "\n");
1805 static int usb_host_info_device(void *opaque
, int bus_num
, int addr
,
1806 char *path
, int class_id
,
1807 int vendor_id
, int product_id
,
1808 const char *product_name
,
1811 Monitor
*mon
= opaque
;
1813 usb_info_device(mon
, bus_num
, addr
, path
, class_id
, vendor_id
, product_id
,
1814 product_name
, speed
);
1818 static void dec2str(int val
, char *str
, size_t size
)
1821 snprintf(str
, size
, "*");
1823 snprintf(str
, size
, "%d", val
);
1827 static void hex2str(int val
, char *str
, size_t size
)
1830 snprintf(str
, size
, "*");
1832 snprintf(str
, size
, "%04x", val
);
1836 void usb_host_info(Monitor
*mon
)
1838 struct USBAutoFilter
*f
;
1839 struct USBHostDevice
*s
;
1841 usb_host_scan(mon
, usb_host_info_device
);
1843 if (QTAILQ_EMPTY(&hostdevs
)) {
1847 monitor_printf(mon
, " Auto filters:\n");
1848 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1849 char bus
[10], addr
[10], vid
[10], pid
[10];
1851 dec2str(f
->bus_num
, bus
, sizeof(bus
));
1852 dec2str(f
->addr
, addr
, sizeof(addr
));
1853 hex2str(f
->vendor_id
, vid
, sizeof(vid
));
1854 hex2str(f
->product_id
, pid
, sizeof(pid
));
1855 monitor_printf(mon
, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1856 bus
, addr
, f
->port
? f
->port
: "*", vid
, pid
);