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 INVALID_EP_TYPE 255
90 /* devio.c limits single requests to 16k */
91 #define MAX_USBFS_BUFFER_SIZE 16384
93 typedef struct AsyncURB AsyncURB
;
106 struct USBAutoFilter
{
114 typedef struct USBHostDevice
{
123 uint32_t iso_urb_count
;
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 struct endp_data
*get_endp(USBHostDevice
*s
, int ep
)
148 return s
->endp_table
+ ep
- 1;
151 static int is_isoc(USBHostDevice
*s
, int ep
)
153 return get_endp(s
, ep
)->type
== USBDEVFS_URB_TYPE_ISO
;
156 static int is_valid(USBHostDevice
*s
, int ep
)
158 return get_endp(s
, ep
)->type
!= INVALID_EP_TYPE
;
161 static int is_halted(USBHostDevice
*s
, int ep
)
163 return get_endp(s
, ep
)->halted
;
166 static void clear_halt(USBHostDevice
*s
, int ep
)
168 get_endp(s
, ep
)->halted
= 0;
171 static void set_halt(USBHostDevice
*s
, int ep
)
173 get_endp(s
, ep
)->halted
= 1;
176 static int is_iso_started(USBHostDevice
*s
, int ep
)
178 return get_endp(s
, ep
)->iso_started
;
181 static void clear_iso_started(USBHostDevice
*s
, int ep
)
183 get_endp(s
, ep
)->iso_started
= 0;
186 static void set_iso_started(USBHostDevice
*s
, int ep
)
188 struct endp_data
*e
= get_endp(s
, ep
);
189 if (!e
->iso_started
) {
195 static int change_iso_inflight(USBHostDevice
*s
, int ep
, int value
)
197 struct endp_data
*e
= get_endp(s
, ep
);
199 e
->inflight
+= value
;
203 static void set_iso_urb(USBHostDevice
*s
, int ep
, AsyncURB
*iso_urb
)
205 get_endp(s
, ep
)->iso_urb
= iso_urb
;
208 static AsyncURB
*get_iso_urb(USBHostDevice
*s
, int ep
)
210 return get_endp(s
, ep
)->iso_urb
;
213 static void set_iso_urb_idx(USBHostDevice
*s
, int ep
, int i
)
215 get_endp(s
, ep
)->iso_urb_idx
= i
;
218 static int get_iso_urb_idx(USBHostDevice
*s
, int ep
)
220 return get_endp(s
, ep
)->iso_urb_idx
;
223 static void set_iso_buffer_used(USBHostDevice
*s
, int ep
, int i
)
225 get_endp(s
, ep
)->iso_buffer_used
= i
;
228 static int get_iso_buffer_used(USBHostDevice
*s
, int ep
)
230 return get_endp(s
, ep
)->iso_buffer_used
;
233 static void set_max_packet_size(USBHostDevice
*s
, int ep
, uint8_t *descriptor
)
235 int raw
= descriptor
[4] + (descriptor
[5] << 8);
236 int size
, microframes
;
239 switch ((raw
>> 11) & 3) {
240 case 1: microframes
= 2; break;
241 case 2: microframes
= 3; break;
242 default: microframes
= 1; break;
244 get_endp(s
, ep
)->max_packet_size
= size
* microframes
;
247 static int get_max_packet_size(USBHostDevice
*s
, int ep
)
249 return get_endp(s
, ep
)->max_packet_size
;
254 * We always allocate iso packet descriptors even for bulk transfers
255 * to simplify allocation and casts.
259 struct usbdevfs_urb urb
;
260 struct usbdevfs_iso_packet_desc isocpd
[ISO_FRAME_DESC_PER_URB
];
262 QLIST_ENTRY(AsyncURB
) next
;
264 /* For regular async urbs */
266 int more
; /* large transfer, more urbs follow */
268 /* For buffered iso handling */
269 int iso_frame_idx
; /* -1 means in flight */
272 static AsyncURB
*async_alloc(USBHostDevice
*s
)
274 AsyncURB
*aurb
= qemu_mallocz(sizeof(AsyncURB
));
276 QLIST_INSERT_HEAD(&s
->aurbs
, aurb
, next
);
280 static void async_free(AsyncURB
*aurb
)
282 QLIST_REMOVE(aurb
, next
);
286 static void do_disconnect(USBHostDevice
*s
)
288 printf("husb: device %d.%d disconnected\n",
289 s
->bus_num
, s
->addr
);
291 usb_host_auto_check(NULL
);
294 static void async_complete(void *opaque
)
296 USBHostDevice
*s
= opaque
;
303 int r
= ioctl(s
->fd
, USBDEVFS_REAPURBNDELAY
, &aurb
);
305 if (errno
== EAGAIN
) {
307 fprintf(stderr
, "husb: %d iso urbs finished at once\n", urbs
);
311 if (errno
== ENODEV
&& !s
->closing
) {
316 DPRINTF("husb: async. reap urb failed errno %d\n", errno
);
320 DPRINTF("husb: async completed. aurb %p status %d alen %d\n",
321 aurb
, aurb
->urb
.status
, aurb
->urb
.actual_length
);
323 /* If this is a buffered iso urb mark it as complete and don't do
324 anything else (it is handled further in usb_host_handle_iso_data) */
325 if (aurb
->iso_frame_idx
== -1) {
327 if (aurb
->urb
.status
== -EPIPE
) {
328 set_halt(s
, aurb
->urb
.endpoint
& 0xf);
330 aurb
->iso_frame_idx
= 0;
332 inflight
= change_iso_inflight(s
, aurb
->urb
.endpoint
& 0xf, -1);
333 if (inflight
== 0 && is_iso_started(s
, aurb
->urb
.endpoint
& 0xf)) {
334 fprintf(stderr
, "husb: out of buffers for iso stream\n");
342 switch (aurb
->urb
.status
) {
344 p
->len
+= aurb
->urb
.actual_length
;
348 set_halt(s
, p
->devep
);
349 p
->len
= USB_RET_STALL
;
353 p
->len
= USB_RET_NAK
;
357 if (aurb
->urb
.type
== USBDEVFS_URB_TYPE_CONTROL
) {
358 usb_generic_async_ctrl_complete(&s
->dev
, p
);
359 } else if (!aurb
->more
) {
360 usb_packet_complete(&s
->dev
, p
);
368 static void usb_host_async_cancel(USBDevice
*dev
, USBPacket
*p
)
370 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
373 QLIST_FOREACH(aurb
, &s
->aurbs
, next
) {
374 if (p
!= aurb
->packet
) {
378 DPRINTF("husb: async cancel: packet %p, aurb %p\n", p
, aurb
);
380 /* Mark it as dead (see async_complete above) */
383 int r
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, aurb
);
385 DPRINTF("husb: async. discard urb failed errno %d\n", errno
);
390 static int usb_host_claim_interfaces(USBHostDevice
*dev
, int configuration
)
392 const char *op
= NULL
;
393 int dev_descr_len
, config_descr_len
;
394 int interface
, nb_interfaces
;
397 if (configuration
== 0) /* address state - ignore */
400 DPRINTF("husb: claiming interfaces. config %d\n", configuration
);
403 dev_descr_len
= dev
->descr
[0];
404 if (dev_descr_len
> dev
->descr_len
) {
405 fprintf(stderr
, "husb: update iface failed. descr too short\n");
410 while (i
< dev
->descr_len
) {
411 DPRINTF("husb: i is %d, descr_len is %d, dl %d, dt %d\n",
413 dev
->descr
[i
], dev
->descr
[i
+1]);
415 if (dev
->descr
[i
+1] != USB_DT_CONFIG
) {
419 config_descr_len
= dev
->descr
[i
];
421 printf("husb: config #%d need %d\n", dev
->descr
[i
+ 5], configuration
);
423 if (configuration
< 0 || configuration
== dev
->descr
[i
+ 5]) {
424 configuration
= dev
->descr
[i
+ 5];
428 i
+= config_descr_len
;
431 if (i
>= dev
->descr_len
) {
433 "husb: update iface failed. no matching configuration\n");
436 nb_interfaces
= dev
->descr
[i
+ 4];
438 #ifdef USBDEVFS_DISCONNECT
439 /* earlier Linux 2.4 do not support that */
441 struct usbdevfs_ioctl ctrl
;
442 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
443 ctrl
.ioctl_code
= USBDEVFS_DISCONNECT
;
444 ctrl
.ifno
= interface
;
446 op
= "USBDEVFS_DISCONNECT";
447 ret
= ioctl(dev
->fd
, USBDEVFS_IOCTL
, &ctrl
);
448 if (ret
< 0 && errno
!= ENODATA
) {
455 /* XXX: only grab if all interfaces are free */
456 for (interface
= 0; interface
< nb_interfaces
; interface
++) {
457 op
= "USBDEVFS_CLAIMINTERFACE";
458 ret
= ioctl(dev
->fd
, USBDEVFS_CLAIMINTERFACE
, &interface
);
460 if (errno
== EBUSY
) {
461 printf("husb: update iface. device already grabbed\n");
463 perror("husb: failed to claim interface");
469 printf("husb: %d interfaces claimed for configuration %d\n",
470 nb_interfaces
, configuration
);
472 dev
->ninterfaces
= nb_interfaces
;
473 dev
->configuration
= configuration
;
477 if (errno
== ENODEV
) {
484 static int usb_host_release_interfaces(USBHostDevice
*s
)
488 DPRINTF("husb: releasing interfaces\n");
490 for (i
= 0; i
< s
->ninterfaces
; i
++) {
491 ret
= ioctl(s
->fd
, USBDEVFS_RELEASEINTERFACE
, &i
);
493 perror("husb: failed to release interface");
501 static void usb_host_handle_reset(USBDevice
*dev
)
503 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
505 DPRINTF("husb: reset device %u.%u\n", s
->bus_num
, s
->addr
);
507 ioctl(s
->fd
, USBDEVFS_RESET
);
509 usb_host_claim_interfaces(s
, s
->configuration
);
512 static void usb_host_handle_destroy(USBDevice
*dev
)
514 USBHostDevice
*s
= (USBHostDevice
*)dev
;
517 QTAILQ_REMOVE(&hostdevs
, s
, next
);
518 qemu_remove_exit_notifier(&s
->exit
);
521 static int usb_linux_update_endp_table(USBHostDevice
*s
);
523 /* iso data is special, we need to keep enough urbs in flight to make sure
524 that the controller never runs out of them, otherwise the device will
525 likely suffer a buffer underrun / overrun. */
526 static AsyncURB
*usb_host_alloc_iso(USBHostDevice
*s
, uint8_t ep
, int in
)
529 int i
, j
, len
= get_max_packet_size(s
, ep
);
531 aurb
= qemu_mallocz(s
->iso_urb_count
* sizeof(*aurb
));
532 for (i
= 0; i
< s
->iso_urb_count
; i
++) {
533 aurb
[i
].urb
.endpoint
= ep
;
534 aurb
[i
].urb
.buffer_length
= ISO_FRAME_DESC_PER_URB
* len
;
535 aurb
[i
].urb
.buffer
= qemu_malloc(aurb
[i
].urb
.buffer_length
);
536 aurb
[i
].urb
.type
= USBDEVFS_URB_TYPE_ISO
;
537 aurb
[i
].urb
.flags
= USBDEVFS_URB_ISO_ASAP
;
538 aurb
[i
].urb
.number_of_packets
= ISO_FRAME_DESC_PER_URB
;
539 for (j
= 0 ; j
< ISO_FRAME_DESC_PER_URB
; j
++)
540 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
542 aurb
[i
].urb
.endpoint
|= 0x80;
543 /* Mark as fully consumed (idle) */
544 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
;
547 set_iso_urb(s
, ep
, aurb
);
552 static void usb_host_stop_n_free_iso(USBHostDevice
*s
, uint8_t ep
)
555 int i
, ret
, killed
= 0, free
= 1;
557 aurb
= get_iso_urb(s
, ep
);
562 for (i
= 0; i
< s
->iso_urb_count
; i
++) {
564 if (aurb
[i
].iso_frame_idx
== -1) {
565 ret
= ioctl(s
->fd
, USBDEVFS_DISCARDURB
, &aurb
[i
]);
567 printf("husb: discard isoc in urb failed errno %d\n", errno
);
575 /* Make sure any urbs we've killed are reaped before we free them */
580 for (i
= 0; i
< s
->iso_urb_count
; i
++) {
581 qemu_free(aurb
[i
].urb
.buffer
);
587 printf("husb: leaking iso urbs because of discard failure\n");
588 set_iso_urb(s
, ep
, NULL
);
589 set_iso_urb_idx(s
, ep
, 0);
590 clear_iso_started(s
, ep
);
593 static int urb_status_to_usb_ret(int status
)
597 return USB_RET_STALL
;
603 static int usb_host_handle_iso_data(USBHostDevice
*s
, USBPacket
*p
, int in
)
606 int i
, j
, ret
, max_packet_size
, offset
, len
= 0;
608 max_packet_size
= get_max_packet_size(s
, p
->devep
);
609 if (max_packet_size
== 0)
612 aurb
= get_iso_urb(s
, p
->devep
);
614 aurb
= usb_host_alloc_iso(s
, p
->devep
, in
);
617 i
= get_iso_urb_idx(s
, p
->devep
);
618 j
= aurb
[i
].iso_frame_idx
;
619 if (j
>= 0 && j
< ISO_FRAME_DESC_PER_URB
) {
621 /* Check urb status */
622 if (aurb
[i
].urb
.status
) {
623 len
= urb_status_to_usb_ret(aurb
[i
].urb
.status
);
624 /* Move to the next urb */
625 aurb
[i
].iso_frame_idx
= ISO_FRAME_DESC_PER_URB
- 1;
626 /* Check frame status */
627 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].status
) {
628 len
= urb_status_to_usb_ret(
629 aurb
[i
].urb
.iso_frame_desc
[j
].status
);
630 /* Check the frame fits */
631 } else if (aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
> p
->len
) {
632 printf("husb: received iso data is larger then packet\n");
634 /* All good copy data over */
636 len
= aurb
[i
].urb
.iso_frame_desc
[j
].actual_length
;
639 j
* aurb
[i
].urb
.iso_frame_desc
[0].length
,
644 offset
= (j
== 0) ? 0 : get_iso_buffer_used(s
, p
->devep
);
646 /* Check the frame fits */
647 if (len
> max_packet_size
) {
648 printf("husb: send iso data is larger then max packet size\n");
652 /* All good copy data over */
653 memcpy(aurb
[i
].urb
.buffer
+ offset
, p
->data
, len
);
654 aurb
[i
].urb
.iso_frame_desc
[j
].length
= len
;
656 set_iso_buffer_used(s
, p
->devep
, offset
);
658 /* Start the stream once we have buffered enough data */
659 if (!is_iso_started(s
, p
->devep
) && i
== 1 && j
== 8) {
660 set_iso_started(s
, p
->devep
);
663 aurb
[i
].iso_frame_idx
++;
664 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
665 i
= (i
+ 1) % s
->iso_urb_count
;
666 set_iso_urb_idx(s
, p
->devep
, i
);
670 set_iso_started(s
, p
->devep
);
672 DPRINTF("hubs: iso out error no free buffer, dropping packet\n");
676 if (is_iso_started(s
, p
->devep
)) {
677 /* (Re)-submit all fully consumed / filled urbs */
678 for (i
= 0; i
< s
->iso_urb_count
; i
++) {
679 if (aurb
[i
].iso_frame_idx
== ISO_FRAME_DESC_PER_URB
) {
680 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, &aurb
[i
]);
682 printf("husb error submitting iso urb %d: %d\n", i
, errno
);
683 if (!in
|| len
== 0) {
695 aurb
[i
].iso_frame_idx
= -1;
696 change_iso_inflight(s
, p
->devep
, +1);
704 static int usb_host_handle_data(USBDevice
*dev
, USBPacket
*p
)
706 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
707 struct usbdevfs_urb
*urb
;
713 if (!is_valid(s
, p
->devep
)) {
717 if (p
->pid
== USB_TOKEN_IN
) {
718 ep
= p
->devep
| 0x80;
723 if (is_halted(s
, p
->devep
)) {
724 ret
= ioctl(s
->fd
, USBDEVFS_CLEAR_HALT
, &ep
);
726 DPRINTF("husb: failed to clear halt. ep 0x%x errno %d\n",
730 clear_halt(s
, p
->devep
);
733 if (is_isoc(s
, p
->devep
)) {
734 return usb_host_handle_iso_data(s
, p
, p
->pid
== USB_TOKEN_IN
);
741 aurb
= async_alloc(s
);
746 urb
->type
= USBDEVFS_URB_TYPE_BULK
;
747 urb
->usercontext
= s
;
750 if (rem
> MAX_USBFS_BUFFER_SIZE
) {
751 urb
->buffer_length
= MAX_USBFS_BUFFER_SIZE
;
754 urb
->buffer_length
= rem
;
757 pbuf
+= urb
->buffer_length
;
758 rem
-= urb
->buffer_length
;
760 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
762 DPRINTF("husb: data submit: ep 0x%x, len %u, more %d, packet %p, aurb %p\n",
763 urb
->endpoint
, urb
->buffer_length
, aurb
->more
, p
, aurb
);
766 DPRINTF("husb: submit failed. errno %d\n", errno
);
774 return USB_RET_STALL
;
779 return USB_RET_ASYNC
;
782 static int ctrl_error(void)
784 if (errno
== ETIMEDOUT
) {
787 return USB_RET_STALL
;
791 static int usb_host_set_address(USBHostDevice
*s
, int addr
)
793 DPRINTF("husb: ctrl set addr %u\n", addr
);
798 static int usb_host_set_config(USBHostDevice
*s
, int config
)
800 usb_host_release_interfaces(s
);
802 int ret
= ioctl(s
->fd
, USBDEVFS_SETCONFIGURATION
, &config
);
804 DPRINTF("husb: ctrl set config %d ret %d errno %d\n", config
, ret
, errno
);
809 usb_host_claim_interfaces(s
, config
);
813 static int usb_host_set_interface(USBHostDevice
*s
, int iface
, int alt
)
815 struct usbdevfs_setinterface si
;
818 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
820 usb_host_stop_n_free_iso(s
, i
);
824 si
.interface
= iface
;
826 ret
= ioctl(s
->fd
, USBDEVFS_SETINTERFACE
, &si
);
828 DPRINTF("husb: ctrl set iface %d altset %d ret %d errno %d\n",
829 iface
, alt
, ret
, errno
);
834 usb_linux_update_endp_table(s
);
838 static int usb_host_handle_control(USBDevice
*dev
, USBPacket
*p
,
839 int request
, int value
, int index
, int length
, uint8_t *data
)
841 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
842 struct usbdevfs_urb
*urb
;
847 * Process certain standard device requests.
848 * These are infrequent and are processed synchronously.
851 /* Note request is (bRequestType << 8) | bRequest */
852 DPRINTF("husb: ctrl type 0x%x req 0x%x val 0x%x index %u len %u\n",
853 request
>> 8, request
& 0xff, value
, index
, length
);
856 case DeviceOutRequest
| USB_REQ_SET_ADDRESS
:
857 return usb_host_set_address(s
, value
);
859 case DeviceOutRequest
| USB_REQ_SET_CONFIGURATION
:
860 return usb_host_set_config(s
, value
& 0xff);
862 case InterfaceOutRequest
| USB_REQ_SET_INTERFACE
:
863 return usb_host_set_interface(s
, index
, value
);
866 /* The rest are asynchronous */
868 if (length
> sizeof(dev
->data_buf
)) {
869 fprintf(stderr
, "husb: ctrl buffer too small (%d > %zu)\n",
870 length
, sizeof(dev
->data_buf
));
871 return USB_RET_STALL
;
874 aurb
= async_alloc(s
);
878 * Setup ctrl transfer.
880 * s->ctrl is laid out such that data buffer immediately follows
881 * 'req' struct which is exactly what usbdevfs expects.
885 urb
->type
= USBDEVFS_URB_TYPE_CONTROL
;
886 urb
->endpoint
= p
->devep
;
888 urb
->buffer
= &dev
->setup_buf
;
889 urb
->buffer_length
= length
+ 8;
891 urb
->usercontext
= s
;
893 ret
= ioctl(s
->fd
, USBDEVFS_SUBMITURB
, urb
);
895 DPRINTF("husb: submit ctrl. len %u aurb %p\n", urb
->buffer_length
, aurb
);
898 DPRINTF("husb: submit failed. errno %d\n", errno
);
906 return USB_RET_STALL
;
910 return USB_RET_ASYNC
;
913 static int usb_linux_get_configuration(USBHostDevice
*s
)
915 uint8_t configuration
;
916 struct usb_ctrltransfer ct
;
919 if (usb_fs_type
== USB_FS_SYS
) {
920 char device_name
[32], line
[1024];
923 sprintf(device_name
, "%d-%s", s
->bus_num
, s
->port
);
925 if (!usb_host_read_file(line
, sizeof(line
), "bConfigurationValue",
929 if (sscanf(line
, "%d", &configuration
) != 1) {
932 return configuration
;
936 ct
.bRequestType
= USB_DIR_IN
;
937 ct
.bRequest
= USB_REQ_GET_CONFIGURATION
;
941 ct
.data
= &configuration
;
944 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
946 perror("usb_linux_get_configuration");
950 /* in address state */
951 if (configuration
== 0) {
955 return configuration
;
958 static uint8_t usb_linux_get_alt_setting(USBHostDevice
*s
,
959 uint8_t configuration
, uint8_t interface
)
962 struct usb_ctrltransfer ct
;
965 if (usb_fs_type
== USB_FS_SYS
) {
966 char device_name
[64], line
[1024];
969 sprintf(device_name
, "%d-%s:%d.%d", s
->bus_num
, s
->port
,
970 (int)configuration
, (int)interface
);
972 if (!usb_host_read_file(line
, sizeof(line
), "bAlternateSetting",
976 if (sscanf(line
, "%d", &alt_setting
) != 1) {
983 ct
.bRequestType
= USB_DIR_IN
| USB_RECIP_INTERFACE
;
984 ct
.bRequest
= USB_REQ_GET_INTERFACE
;
986 ct
.wIndex
= interface
;
988 ct
.data
= &alt_setting
;
990 ret
= ioctl(s
->fd
, USBDEVFS_CONTROL
, &ct
);
992 /* Assume alt 0 on error */
999 /* returns 1 on problem encountered or 0 for success */
1000 static int usb_linux_update_endp_table(USBHostDevice
*s
)
1002 uint8_t *descriptors
;
1003 uint8_t devep
, type
, configuration
, alt_interface
;
1004 int interface
, length
, i
;
1006 for (i
= 0; i
< MAX_ENDPOINTS
; i
++)
1007 s
->endp_table
[i
].type
= INVALID_EP_TYPE
;
1009 i
= usb_linux_get_configuration(s
);
1014 /* get the desired configuration, interface, and endpoint descriptors
1015 * from device description */
1016 descriptors
= &s
->descr
[18];
1017 length
= s
->descr_len
- 18;
1020 if (descriptors
[i
+ 1] != USB_DT_CONFIG
||
1021 descriptors
[i
+ 5] != configuration
) {
1022 DPRINTF("invalid descriptor data - configuration\n");
1025 i
+= descriptors
[i
];
1027 while (i
< length
) {
1028 if (descriptors
[i
+ 1] != USB_DT_INTERFACE
||
1029 (descriptors
[i
+ 1] == USB_DT_INTERFACE
&&
1030 descriptors
[i
+ 4] == 0)) {
1031 i
+= descriptors
[i
];
1035 interface
= descriptors
[i
+ 2];
1036 alt_interface
= usb_linux_get_alt_setting(s
, configuration
, interface
);
1038 /* the current interface descriptor is the active interface
1039 * and has endpoints */
1040 if (descriptors
[i
+ 3] != alt_interface
) {
1041 i
+= descriptors
[i
];
1045 /* advance to the endpoints */
1046 while (i
< length
&& descriptors
[i
+1] != USB_DT_ENDPOINT
) {
1047 i
+= descriptors
[i
];
1053 while (i
< length
) {
1054 if (descriptors
[i
+ 1] != USB_DT_ENDPOINT
) {
1058 devep
= descriptors
[i
+ 2];
1059 if ((devep
& 0x0f) == 0) {
1060 fprintf(stderr
, "usb-linux: invalid ep descriptor, ep == 0\n");
1064 switch (descriptors
[i
+ 3] & 0x3) {
1066 type
= USBDEVFS_URB_TYPE_CONTROL
;
1069 type
= USBDEVFS_URB_TYPE_ISO
;
1070 set_max_packet_size(s
, (devep
& 0xf), descriptors
+ i
);
1073 type
= USBDEVFS_URB_TYPE_BULK
;
1076 type
= USBDEVFS_URB_TYPE_INTERRUPT
;
1079 DPRINTF("usb_host: malformed endpoint type\n");
1080 type
= USBDEVFS_URB_TYPE_BULK
;
1082 s
->endp_table
[(devep
& 0xf) - 1].type
= type
;
1083 s
->endp_table
[(devep
& 0xf) - 1].halted
= 0;
1085 i
+= descriptors
[i
];
1091 static int usb_host_open(USBHostDevice
*dev
, int bus_num
,
1092 int addr
, char *port
, const char *prod_name
, int speed
)
1097 if (dev
->fd
!= -1) {
1100 printf("husb: open device %d.%d\n", bus_num
, addr
);
1102 if (!usb_host_device_path
) {
1103 perror("husb: USB Host Device Path not set");
1106 snprintf(buf
, sizeof(buf
), "%s/%03d/%03d", usb_host_device_path
,
1108 fd
= open(buf
, O_RDWR
| O_NONBLOCK
);
1113 DPRINTF("husb: opened %s\n", buf
);
1115 dev
->bus_num
= bus_num
;
1117 strcpy(dev
->port
, port
);
1120 /* read the device description */
1121 dev
->descr_len
= read(fd
, dev
->descr
, sizeof(dev
->descr
));
1122 if (dev
->descr_len
<= 0) {
1123 perror("husb: reading device data failed");
1130 printf("=== begin dumping device descriptor data ===\n");
1131 for (x
= 0; x
< dev
->descr_len
; x
++) {
1132 printf("%02x ", dev
->descr
[x
]);
1134 printf("\n=== end dumping device descriptor data ===\n");
1140 * Initial configuration is -1 which makes us claim first
1141 * available config. We used to start with 1, which does not
1142 * always work. I've seen devices where first config starts
1145 if (!usb_host_claim_interfaces(dev
, -1)) {
1149 ret
= usb_linux_update_endp_table(dev
);
1155 struct usbdevfs_connectinfo ci
;
1157 ret
= ioctl(fd
, USBDEVFS_CONNECTINFO
, &ci
);
1159 perror("usb_host_device_open: USBDEVFS_CONNECTINFO");
1164 speed
= USB_SPEED_LOW
;
1166 speed
= USB_SPEED_HIGH
;
1169 dev
->dev
.speed
= speed
;
1171 printf("husb: grabbed usb device %d.%d\n", bus_num
, addr
);
1173 if (!prod_name
|| prod_name
[0] == '\0') {
1174 snprintf(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1175 "host:%d.%d", bus_num
, addr
);
1177 pstrcpy(dev
->dev
.product_desc
, sizeof(dev
->dev
.product_desc
),
1181 /* USB devio uses 'write' flag to check for async completions */
1182 qemu_set_fd_handler(dev
->fd
, NULL
, async_complete
, dev
);
1184 usb_device_attach(&dev
->dev
);
1188 if (dev
->fd
!= -1) {
1195 static int usb_host_close(USBHostDevice
*dev
)
1199 if (dev
->fd
== -1 || !dev
->dev
.attached
) {
1203 qemu_set_fd_handler(dev
->fd
, NULL
, NULL
, NULL
);
1205 for (i
= 1; i
<= MAX_ENDPOINTS
; i
++) {
1206 if (is_isoc(dev
, i
)) {
1207 usb_host_stop_n_free_iso(dev
, i
);
1210 async_complete(dev
);
1212 usb_device_detach(&dev
->dev
);
1213 ioctl(dev
->fd
, USBDEVFS_RESET
);
1219 static void usb_host_exit_notifier(struct Notifier
* n
)
1221 USBHostDevice
*s
= container_of(n
, USBHostDevice
, exit
);
1224 ioctl(s
->fd
, USBDEVFS_RESET
);
1228 static int usb_host_initfn(USBDevice
*dev
)
1230 USBHostDevice
*s
= DO_UPCAST(USBHostDevice
, dev
, dev
);
1232 dev
->auto_attach
= 0;
1234 QTAILQ_INSERT_TAIL(&hostdevs
, s
, next
);
1235 s
->exit
.notify
= usb_host_exit_notifier
;
1236 qemu_add_exit_notifier(&s
->exit
);
1237 usb_host_auto_check(NULL
);
1241 static struct USBDeviceInfo usb_host_dev_info
= {
1242 .product_desc
= "USB Host Device",
1243 .qdev
.name
= "usb-host",
1244 .qdev
.size
= sizeof(USBHostDevice
),
1245 .init
= usb_host_initfn
,
1246 .handle_packet
= usb_generic_handle_packet
,
1247 .cancel_packet
= usb_host_async_cancel
,
1248 .handle_data
= usb_host_handle_data
,
1249 .handle_control
= usb_host_handle_control
,
1250 .handle_reset
= usb_host_handle_reset
,
1251 .handle_destroy
= usb_host_handle_destroy
,
1252 .usbdevice_name
= "host",
1253 .usbdevice_init
= usb_host_device_open
,
1254 .qdev
.props
= (Property
[]) {
1255 DEFINE_PROP_UINT32("hostbus", USBHostDevice
, match
.bus_num
, 0),
1256 DEFINE_PROP_UINT32("hostaddr", USBHostDevice
, match
.addr
, 0),
1257 DEFINE_PROP_STRING("hostport", USBHostDevice
, match
.port
),
1258 DEFINE_PROP_HEX32("vendorid", USBHostDevice
, match
.vendor_id
, 0),
1259 DEFINE_PROP_HEX32("productid", USBHostDevice
, match
.product_id
, 0),
1260 DEFINE_PROP_UINT32("isobufs", USBHostDevice
, iso_urb_count
, 4),
1261 DEFINE_PROP_END_OF_LIST(),
1265 static void usb_host_register_devices(void)
1267 usb_qdev_register(&usb_host_dev_info
);
1269 device_init(usb_host_register_devices
)
1271 USBDevice
*usb_host_device_open(const char *devname
)
1273 struct USBAutoFilter filter
;
1277 dev
= usb_create(NULL
/* FIXME */, "usb-host");
1279 if (strstr(devname
, "auto:")) {
1280 if (parse_filter(devname
, &filter
) < 0) {
1284 if ((p
= strchr(devname
, '.'))) {
1285 filter
.bus_num
= strtoul(devname
, NULL
, 0);
1286 filter
.addr
= strtoul(p
+ 1, NULL
, 0);
1287 filter
.vendor_id
= 0;
1288 filter
.product_id
= 0;
1289 } else if ((p
= strchr(devname
, ':'))) {
1292 filter
.vendor_id
= strtoul(devname
, NULL
, 16);
1293 filter
.product_id
= strtoul(p
+ 1, NULL
, 16);
1299 qdev_prop_set_uint32(&dev
->qdev
, "hostbus", filter
.bus_num
);
1300 qdev_prop_set_uint32(&dev
->qdev
, "hostaddr", filter
.addr
);
1301 qdev_prop_set_uint32(&dev
->qdev
, "vendorid", filter
.vendor_id
);
1302 qdev_prop_set_uint32(&dev
->qdev
, "productid", filter
.product_id
);
1303 qdev_init_nofail(&dev
->qdev
);
1307 qdev_free(&dev
->qdev
);
1311 int usb_host_device_close(const char *devname
)
1314 char product_name
[PRODUCT_NAME_SZ
];
1318 if (strstr(devname
, "auto:")) {
1319 return usb_host_auto_del(devname
);
1321 if (usb_host_find_device(&bus_num
, &addr
, product_name
,
1322 sizeof(product_name
), devname
) < 0) {
1325 s
= hostdev_find(bus_num
, addr
);
1327 usb_device_delete_addr(s
->bus_num
, s
->dev
.addr
);
1335 static int get_tag_value(char *buf
, int buf_size
,
1336 const char *str
, const char *tag
,
1337 const char *stopchars
)
1341 p
= strstr(str
, tag
);
1346 while (qemu_isspace(*p
)) {
1350 while (*p
!= '\0' && !strchr(stopchars
, *p
)) {
1351 if ((q
- buf
) < (buf_size
- 1)) {
1361 * Use /proc/bus/usb/devices or /dev/bus/usb/devices file to determine
1362 * host's USB devices. This is legacy support since many distributions
1363 * are moving to /sys/bus/usb
1365 static int usb_host_scan_dev(void *opaque
, USBScanFunc
*func
)
1370 int bus_num
, addr
, speed
, device_count
, class_id
, product_id
, vendor_id
;
1371 char product_name
[512];
1374 if (!usb_host_device_path
) {
1375 perror("husb: USB Host Device Path not set");
1378 snprintf(line
, sizeof(line
), "%s/devices", usb_host_device_path
);
1379 f
= fopen(line
, "r");
1381 perror("husb: cannot open devices file");
1386 bus_num
= addr
= class_id
= product_id
= vendor_id
= 0;
1387 speed
= -1; /* Can't get the speed from /[proc|dev]/bus/usb/devices */
1389 if (fgets(line
, sizeof(line
), f
) == NULL
) {
1392 if (strlen(line
) > 0) {
1393 line
[strlen(line
) - 1] = '\0';
1395 if (line
[0] == 'T' && line
[1] == ':') {
1396 if (device_count
&& (vendor_id
|| product_id
)) {
1397 /* New device. Add the previously discovered device. */
1398 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1399 product_id
, product_name
, speed
);
1404 if (get_tag_value(buf
, sizeof(buf
), line
, "Bus=", " ") < 0) {
1407 bus_num
= atoi(buf
);
1408 if (get_tag_value(buf
, sizeof(buf
), line
, "Dev#=", " ") < 0) {
1412 if (get_tag_value(buf
, sizeof(buf
), line
, "Spd=", " ") < 0) {
1415 if (!strcmp(buf
, "5000")) {
1416 speed
= USB_SPEED_SUPER
;
1417 } else if (!strcmp(buf
, "480")) {
1418 speed
= USB_SPEED_HIGH
;
1419 } else if (!strcmp(buf
, "1.5")) {
1420 speed
= USB_SPEED_LOW
;
1422 speed
= USB_SPEED_FULL
;
1424 product_name
[0] = '\0';
1429 } else if (line
[0] == 'P' && line
[1] == ':') {
1430 if (get_tag_value(buf
, sizeof(buf
), line
, "Vendor=", " ") < 0) {
1433 vendor_id
= strtoul(buf
, NULL
, 16);
1434 if (get_tag_value(buf
, sizeof(buf
), line
, "ProdID=", " ") < 0) {
1437 product_id
= strtoul(buf
, NULL
, 16);
1438 } else if (line
[0] == 'S' && line
[1] == ':') {
1439 if (get_tag_value(buf
, sizeof(buf
), line
, "Product=", "") < 0) {
1442 pstrcpy(product_name
, sizeof(product_name
), buf
);
1443 } else if (line
[0] == 'D' && line
[1] == ':') {
1444 if (get_tag_value(buf
, sizeof(buf
), line
, "Cls=", " (") < 0) {
1447 class_id
= strtoul(buf
, NULL
, 16);
1451 if (device_count
&& (vendor_id
|| product_id
)) {
1452 /* Add the last device. */
1453 ret
= func(opaque
, bus_num
, addr
, 0, class_id
, vendor_id
,
1454 product_id
, product_name
, speed
);
1464 * Read sys file-system device file
1466 * @line address of buffer to put file contents in
1467 * @line_size size of line
1468 * @device_file path to device file (printf format string)
1469 * @device_name device being opened (inserted into device_file)
1471 * @return 0 failed, 1 succeeded ('line' contains data)
1473 static int usb_host_read_file(char *line
, size_t line_size
,
1474 const char *device_file
, const char *device_name
)
1478 char filename
[PATH_MAX
];
1480 snprintf(filename
, PATH_MAX
, USBSYSBUS_PATH
"/devices/%s/%s", device_name
,
1482 f
= fopen(filename
, "r");
1484 ret
= fgets(line
, line_size
, f
) != NULL
;
1492 * Use /sys/bus/usb/devices/ directory to determine host's USB
1495 * This code is based on Robert Schiele's original patches posted to
1496 * the Novell bug-tracker https://bugzilla.novell.com/show_bug.cgi?id=241950
1498 static int usb_host_scan_sys(void *opaque
, USBScanFunc
*func
)
1502 int bus_num
, addr
, speed
, class_id
, product_id
, vendor_id
;
1504 char port
[MAX_PORTLEN
];
1505 char product_name
[512];
1508 dir
= opendir(USBSYSBUS_PATH
"/devices");
1510 perror("husb: cannot open devices directory");
1514 while ((de
= readdir(dir
))) {
1515 if (de
->d_name
[0] != '.' && !strchr(de
->d_name
, ':')) {
1516 if (sscanf(de
->d_name
, "%d-%7[0-9.]", &bus_num
, port
) < 2) {
1520 if (!usb_host_read_file(line
, sizeof(line
), "devnum", de
->d_name
)) {
1523 if (sscanf(line
, "%d", &addr
) != 1) {
1526 if (!usb_host_read_file(line
, sizeof(line
), "bDeviceClass",
1530 if (sscanf(line
, "%x", &class_id
) != 1) {
1534 if (!usb_host_read_file(line
, sizeof(line
), "idVendor",
1538 if (sscanf(line
, "%x", &vendor_id
) != 1) {
1541 if (!usb_host_read_file(line
, sizeof(line
), "idProduct",
1545 if (sscanf(line
, "%x", &product_id
) != 1) {
1548 if (!usb_host_read_file(line
, sizeof(line
), "product",
1552 if (strlen(line
) > 0) {
1553 line
[strlen(line
) - 1] = '\0';
1555 pstrcpy(product_name
, sizeof(product_name
), line
);
1558 if (!usb_host_read_file(line
, sizeof(line
), "speed", de
->d_name
)) {
1561 if (!strcmp(line
, "5000\n")) {
1562 speed
= USB_SPEED_SUPER
;
1563 } else if (!strcmp(line
, "480\n")) {
1564 speed
= USB_SPEED_HIGH
;
1565 } else if (!strcmp(line
, "1.5\n")) {
1566 speed
= USB_SPEED_LOW
;
1568 speed
= USB_SPEED_FULL
;
1571 ret
= func(opaque
, bus_num
, addr
, port
, class_id
, vendor_id
,
1572 product_id
, product_name
, speed
);
1586 * Determine how to access the host's USB devices and call the
1587 * specific support function.
1589 static int usb_host_scan(void *opaque
, USBScanFunc
*func
)
1591 Monitor
*mon
= cur_mon
;
1595 const char *fs_type
[] = {"unknown", "proc", "dev", "sys"};
1596 char devpath
[PATH_MAX
];
1598 /* only check the host once */
1600 dir
= opendir(USBSYSBUS_PATH
"/devices");
1602 /* devices found in /dev/bus/usb/ (yes - not a mistake!) */
1603 strcpy(devpath
, USBDEVBUS_PATH
);
1604 usb_fs_type
= USB_FS_SYS
;
1606 DPRINTF(USBDBG_DEVOPENED
, USBSYSBUS_PATH
);
1609 f
= fopen(USBPROCBUS_PATH
"/devices", "r");
1611 /* devices found in /proc/bus/usb/ */
1612 strcpy(devpath
, USBPROCBUS_PATH
);
1613 usb_fs_type
= USB_FS_PROC
;
1615 DPRINTF(USBDBG_DEVOPENED
, USBPROCBUS_PATH
);
1618 /* try additional methods if an access method hasn't been found yet */
1619 f
= fopen(USBDEVBUS_PATH
"/devices", "r");
1621 /* devices found in /dev/bus/usb/ */
1622 strcpy(devpath
, USBDEVBUS_PATH
);
1623 usb_fs_type
= USB_FS_DEV
;
1625 DPRINTF(USBDBG_DEVOPENED
, USBDEVBUS_PATH
);
1631 monitor_printf(mon
, "husb: unable to access USB devices\n");
1636 /* the module setting (used later for opening devices) */
1637 usb_host_device_path
= qemu_mallocz(strlen(devpath
)+1);
1638 strcpy(usb_host_device_path
, devpath
);
1640 monitor_printf(mon
, "husb: using %s file-system with %s\n",
1641 fs_type
[usb_fs_type
], usb_host_device_path
);
1645 switch (usb_fs_type
) {
1648 ret
= usb_host_scan_dev(opaque
, func
);
1651 ret
= usb_host_scan_sys(opaque
, func
);
1660 static QEMUTimer
*usb_auto_timer
;
1662 static int usb_host_auto_scan(void *opaque
, int bus_num
, int addr
, char *port
,
1663 int class_id
, int vendor_id
, int product_id
,
1664 const char *product_name
, int speed
)
1666 struct USBAutoFilter
*f
;
1667 struct USBHostDevice
*s
;
1673 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1676 if (f
->bus_num
> 0 && f
->bus_num
!= bus_num
) {
1679 if (f
->addr
> 0 && f
->addr
!= addr
) {
1682 if (f
->port
!= NULL
&& (port
== NULL
|| strcmp(f
->port
, port
) != 0)) {
1686 if (f
->vendor_id
> 0 && f
->vendor_id
!= vendor_id
) {
1690 if (f
->product_id
> 0 && f
->product_id
!= product_id
) {
1693 /* We got a match */
1695 /* Already attached ? */
1699 DPRINTF("husb: auto open: bus_num %d addr %d\n", bus_num
, addr
);
1701 usb_host_open(s
, bus_num
, addr
, port
, product_name
, speed
);
1708 static void usb_host_auto_check(void *unused
)
1710 struct USBHostDevice
*s
;
1711 int unconnected
= 0;
1713 usb_host_scan(NULL
, usb_host_auto_scan
);
1715 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1721 if (unconnected
== 0) {
1722 /* nothing to watch */
1723 if (usb_auto_timer
) {
1724 qemu_del_timer(usb_auto_timer
);
1729 if (!usb_auto_timer
) {
1730 usb_auto_timer
= qemu_new_timer_ms(rt_clock
, usb_host_auto_check
, NULL
);
1731 if (!usb_auto_timer
) {
1735 qemu_mod_timer(usb_auto_timer
, qemu_get_clock_ms(rt_clock
) + 2000);
1739 * Autoconnect filter
1741 * auto:bus:dev[:vid:pid]
1742 * auto:bus.dev[:vid:pid]
1744 * bus - bus number (dec, * means any)
1745 * dev - device number (dec, * means any)
1746 * vid - vendor id (hex, * means any)
1747 * pid - product id (hex, * means any)
1749 * See 'lsusb' output.
1751 static int parse_filter(const char *spec
, struct USBAutoFilter
*f
)
1753 enum { BUS
, DEV
, VID
, PID
, DONE
};
1754 const char *p
= spec
;
1762 for (i
= BUS
; i
< DONE
; i
++) {
1763 p
= strpbrk(p
, ":.");
1773 case BUS
: f
->bus_num
= strtol(p
, NULL
, 10); break;
1774 case DEV
: f
->addr
= strtol(p
, NULL
, 10); break;
1775 case VID
: f
->vendor_id
= strtol(p
, NULL
, 16); break;
1776 case PID
: f
->product_id
= strtol(p
, NULL
, 16); break;
1781 fprintf(stderr
, "husb: invalid auto filter spec %s\n", spec
);
1788 /**********************/
1789 /* USB host device info */
1791 struct usb_class_info
{
1793 const char *class_name
;
1796 static const struct usb_class_info usb_class_info
[] = {
1797 { USB_CLASS_AUDIO
, "Audio"},
1798 { USB_CLASS_COMM
, "Communication"},
1799 { USB_CLASS_HID
, "HID"},
1800 { USB_CLASS_HUB
, "Hub" },
1801 { USB_CLASS_PHYSICAL
, "Physical" },
1802 { USB_CLASS_PRINTER
, "Printer" },
1803 { USB_CLASS_MASS_STORAGE
, "Storage" },
1804 { USB_CLASS_CDC_DATA
, "Data" },
1805 { USB_CLASS_APP_SPEC
, "Application Specific" },
1806 { USB_CLASS_VENDOR_SPEC
, "Vendor Specific" },
1807 { USB_CLASS_STILL_IMAGE
, "Still Image" },
1808 { USB_CLASS_CSCID
, "Smart Card" },
1809 { USB_CLASS_CONTENT_SEC
, "Content Security" },
1813 static const char *usb_class_str(uint8_t class)
1815 const struct usb_class_info
*p
;
1816 for(p
= usb_class_info
; p
->class != -1; p
++) {
1817 if (p
->class == class) {
1821 return p
->class_name
;
1824 static void usb_info_device(Monitor
*mon
, int bus_num
, int addr
, char *port
,
1825 int class_id
, int vendor_id
, int product_id
,
1826 const char *product_name
,
1829 const char *class_str
, *speed_str
;
1835 case USB_SPEED_FULL
:
1838 case USB_SPEED_HIGH
:
1841 case USB_SPEED_SUPER
:
1849 monitor_printf(mon
, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n",
1850 bus_num
, addr
, port
, speed_str
);
1851 class_str
= usb_class_str(class_id
);
1853 monitor_printf(mon
, " %s:", class_str
);
1855 monitor_printf(mon
, " Class %02x:", class_id
);
1857 monitor_printf(mon
, " USB device %04x:%04x", vendor_id
, product_id
);
1858 if (product_name
[0] != '\0') {
1859 monitor_printf(mon
, ", %s", product_name
);
1861 monitor_printf(mon
, "\n");
1864 static int usb_host_info_device(void *opaque
, int bus_num
, int addr
,
1865 char *path
, int class_id
,
1866 int vendor_id
, int product_id
,
1867 const char *product_name
,
1870 Monitor
*mon
= opaque
;
1872 usb_info_device(mon
, bus_num
, addr
, path
, class_id
, vendor_id
, product_id
,
1873 product_name
, speed
);
1877 static void dec2str(int val
, char *str
, size_t size
)
1880 snprintf(str
, size
, "*");
1882 snprintf(str
, size
, "%d", val
);
1886 static void hex2str(int val
, char *str
, size_t size
)
1889 snprintf(str
, size
, "*");
1891 snprintf(str
, size
, "%04x", val
);
1895 void usb_host_info(Monitor
*mon
)
1897 struct USBAutoFilter
*f
;
1898 struct USBHostDevice
*s
;
1900 usb_host_scan(mon
, usb_host_info_device
);
1902 if (QTAILQ_EMPTY(&hostdevs
)) {
1906 monitor_printf(mon
, " Auto filters:\n");
1907 QTAILQ_FOREACH(s
, &hostdevs
, next
) {
1908 char bus
[10], addr
[10], vid
[10], pid
[10];
1910 dec2str(f
->bus_num
, bus
, sizeof(bus
));
1911 dec2str(f
->addr
, addr
, sizeof(addr
));
1912 hex2str(f
->vendor_id
, vid
, sizeof(vid
));
1913 hex2str(f
->product_id
, pid
, sizeof(pid
));
1914 monitor_printf(mon
, " Bus %s, Addr %s, Port %s, ID %s:%s\n",
1915 bus
, addr
, f
->port
? f
->port
: "*", vid
, pid
);