12b2325ffSGerd Hoffmann /* 22b2325ffSGerd Hoffmann * Linux host USB redirector 32b2325ffSGerd Hoffmann * 42b2325ffSGerd Hoffmann * Copyright (c) 2005 Fabrice Bellard 52b2325ffSGerd Hoffmann * 62b2325ffSGerd Hoffmann * Copyright (c) 2008 Max Krasnyansky 72b2325ffSGerd Hoffmann * Support for host device auto connect & disconnect 82b2325ffSGerd Hoffmann * Major rewrite to support fully async operation 92b2325ffSGerd Hoffmann * 102b2325ffSGerd Hoffmann * Copyright 2008 TJ <linux@tjworld.net> 112b2325ffSGerd Hoffmann * Added flexible support for /dev/bus/usb /sys/bus/usb/devices in addition 122b2325ffSGerd Hoffmann * to the legacy /proc/bus/usb USB device discovery and handling 132b2325ffSGerd Hoffmann * 142b2325ffSGerd Hoffmann * (c) 2012 Gerd Hoffmann <kraxel@redhat.com> 152b2325ffSGerd Hoffmann * Completely rewritten to use libusb instead of usbfs ioctls. 162b2325ffSGerd Hoffmann * 172b2325ffSGerd Hoffmann * Permission is hereby granted, free of charge, to any person obtaining a copy 182b2325ffSGerd Hoffmann * of this software and associated documentation files (the "Software"), to deal 192b2325ffSGerd Hoffmann * in the Software without restriction, including without limitation the rights 202b2325ffSGerd Hoffmann * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 212b2325ffSGerd Hoffmann * copies of the Software, and to permit persons to whom the Software is 222b2325ffSGerd Hoffmann * furnished to do so, subject to the following conditions: 232b2325ffSGerd Hoffmann * 242b2325ffSGerd Hoffmann * The above copyright notice and this permission notice shall be included in 252b2325ffSGerd Hoffmann * all copies or substantial portions of the Software. 262b2325ffSGerd Hoffmann * 272b2325ffSGerd Hoffmann * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 282b2325ffSGerd Hoffmann * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 292b2325ffSGerd Hoffmann * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 302b2325ffSGerd Hoffmann * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 312b2325ffSGerd Hoffmann * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 322b2325ffSGerd Hoffmann * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 332b2325ffSGerd Hoffmann * THE SOFTWARE. 342b2325ffSGerd Hoffmann */ 352b2325ffSGerd Hoffmann 36e532b2e0SPeter Maydell #include "qemu/osdep.h" 37db1015e9SEduardo Habkost #include "qom/object.h" 38a277c3e0SStefan Weil #ifndef CONFIG_WIN32 392b2325ffSGerd Hoffmann #include <poll.h> 40a277c3e0SStefan Weil #endif 412b2325ffSGerd Hoffmann #include <libusb.h> 422b2325ffSGerd Hoffmann 43202d69a7SGerd Hoffmann #ifdef CONFIG_LINUX 44202d69a7SGerd Hoffmann #include <sys/ioctl.h> 45202d69a7SGerd Hoffmann #include <linux/usbdevice_fs.h> 46202d69a7SGerd Hoffmann #endif 47202d69a7SGerd Hoffmann 48da34e65cSMarkus Armbruster #include "qapi/error.h" 49d6454270SMarkus Armbruster #include "migration/vmstate.h" 502b2325ffSGerd Hoffmann #include "monitor/monitor.h" 51d49b6836SMarkus Armbruster #include "qemu/error-report.h" 52db725815SMarkus Armbruster #include "qemu/main-loop.h" 530b8fa32fSMarkus Armbruster #include "qemu/module.h" 5454d31236SMarkus Armbruster #include "sysemu/runstate.h" 552b2325ffSGerd Hoffmann #include "sysemu/sysemu.h" 562b2325ffSGerd Hoffmann #include "trace.h" 572b2325ffSGerd Hoffmann 58a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 592b2325ffSGerd Hoffmann #include "hw/usb.h" 602b2325ffSGerd Hoffmann 612b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 622b2325ffSGerd Hoffmann 632b2325ffSGerd Hoffmann #define TYPE_USB_HOST_DEVICE "usb-host" 648063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(USBHostDevice, USB_HOST_DEVICE) 652b2325ffSGerd Hoffmann 662b2325ffSGerd Hoffmann typedef struct USBHostRequest USBHostRequest; 672b2325ffSGerd Hoffmann typedef struct USBHostIsoXfer USBHostIsoXfer; 682b2325ffSGerd Hoffmann typedef struct USBHostIsoRing USBHostIsoRing; 692b2325ffSGerd Hoffmann 702b2325ffSGerd Hoffmann struct USBAutoFilter { 712b2325ffSGerd Hoffmann uint32_t bus_num; 722b2325ffSGerd Hoffmann uint32_t addr; 732b2325ffSGerd Hoffmann char *port; 742b2325ffSGerd Hoffmann uint32_t vendor_id; 752b2325ffSGerd Hoffmann uint32_t product_id; 762b2325ffSGerd Hoffmann }; 772b2325ffSGerd Hoffmann 782b2325ffSGerd Hoffmann enum USBHostDeviceOptions { 792b2325ffSGerd Hoffmann USB_HOST_OPT_PIPELINE, 802b2325ffSGerd Hoffmann }; 812b2325ffSGerd Hoffmann 822b2325ffSGerd Hoffmann struct USBHostDevice { 832b2325ffSGerd Hoffmann USBDevice parent_obj; 842b2325ffSGerd Hoffmann 852b2325ffSGerd Hoffmann /* properties */ 862b2325ffSGerd Hoffmann struct USBAutoFilter match; 879f815e83SGerd Hoffmann char *hostdevice; 882b2325ffSGerd Hoffmann int32_t bootindex; 892b2325ffSGerd Hoffmann uint32_t iso_urb_count; 902b2325ffSGerd Hoffmann uint32_t iso_urb_frames; 912b2325ffSGerd Hoffmann uint32_t options; 922b2325ffSGerd Hoffmann uint32_t loglevel; 93e058fa2dSGerd Hoffmann bool needs_autoscan; 941dfe2b91SGerd Hoffmann bool allow_one_guest_reset; 951dfe2b91SGerd Hoffmann bool allow_all_guest_resets; 967bacaf5fSYuri Benditovich bool suppress_remote_wake; 971dfe2b91SGerd Hoffmann 982b2325ffSGerd Hoffmann /* state */ 992b2325ffSGerd Hoffmann QTAILQ_ENTRY(USBHostDevice) next; 1002b2325ffSGerd Hoffmann int seen, errcount; 1012b2325ffSGerd Hoffmann int bus_num; 1022b2325ffSGerd Hoffmann int addr; 1032b2325ffSGerd Hoffmann char port[16]; 1042b2325ffSGerd Hoffmann 1059f815e83SGerd Hoffmann int hostfd; 1062b2325ffSGerd Hoffmann libusb_device *dev; 1072b2325ffSGerd Hoffmann libusb_device_handle *dh; 1082b2325ffSGerd Hoffmann struct libusb_device_descriptor ddesc; 1092b2325ffSGerd Hoffmann 1102b2325ffSGerd Hoffmann struct { 1112b2325ffSGerd Hoffmann bool detached; 1122b2325ffSGerd Hoffmann bool claimed; 1132b2325ffSGerd Hoffmann } ifs[USB_MAX_INTERFACES]; 1142b2325ffSGerd Hoffmann 1152b2325ffSGerd Hoffmann /* callbacks & friends */ 11695efb20cSGerd Hoffmann QEMUBH *bh_nodev; 11795efb20cSGerd Hoffmann QEMUBH *bh_postld; 1183280ea8eSGerd Hoffmann bool bh_postld_pending; 1192b2325ffSGerd Hoffmann Notifier exit; 1202b2325ffSGerd Hoffmann 1212b2325ffSGerd Hoffmann /* request queues */ 1222b2325ffSGerd Hoffmann QTAILQ_HEAD(, USBHostRequest) requests; 1232b2325ffSGerd Hoffmann QTAILQ_HEAD(, USBHostIsoRing) isorings; 1242b2325ffSGerd Hoffmann }; 1252b2325ffSGerd Hoffmann 1262b2325ffSGerd Hoffmann struct USBHostRequest { 1272b2325ffSGerd Hoffmann USBHostDevice *host; 1282b2325ffSGerd Hoffmann USBPacket *p; 1292b2325ffSGerd Hoffmann bool in; 1302b2325ffSGerd Hoffmann struct libusb_transfer *xfer; 1312b2325ffSGerd Hoffmann unsigned char *buffer; 1322b2325ffSGerd Hoffmann unsigned char *cbuf; 1332b2325ffSGerd Hoffmann unsigned int clen; 134b88a3e01SGerd Hoffmann bool usb3ep0quirk; 1352b2325ffSGerd Hoffmann QTAILQ_ENTRY(USBHostRequest) next; 1362b2325ffSGerd Hoffmann }; 1372b2325ffSGerd Hoffmann 1382b2325ffSGerd Hoffmann struct USBHostIsoXfer { 1392b2325ffSGerd Hoffmann USBHostIsoRing *ring; 1402b2325ffSGerd Hoffmann struct libusb_transfer *xfer; 1412b2325ffSGerd Hoffmann bool copy_complete; 1422b2325ffSGerd Hoffmann unsigned int packet; 1432b2325ffSGerd Hoffmann QTAILQ_ENTRY(USBHostIsoXfer) next; 1442b2325ffSGerd Hoffmann }; 1452b2325ffSGerd Hoffmann 1462b2325ffSGerd Hoffmann struct USBHostIsoRing { 1472b2325ffSGerd Hoffmann USBHostDevice *host; 1482b2325ffSGerd Hoffmann USBEndpoint *ep; 1492b2325ffSGerd Hoffmann QTAILQ_HEAD(, USBHostIsoXfer) unused; 1502b2325ffSGerd Hoffmann QTAILQ_HEAD(, USBHostIsoXfer) inflight; 1512b2325ffSGerd Hoffmann QTAILQ_HEAD(, USBHostIsoXfer) copy; 1522b2325ffSGerd Hoffmann QTAILQ_ENTRY(USBHostIsoRing) next; 1532b2325ffSGerd Hoffmann }; 1542b2325ffSGerd Hoffmann 1552b2325ffSGerd Hoffmann static QTAILQ_HEAD(, USBHostDevice) hostdevs = 1562b2325ffSGerd Hoffmann QTAILQ_HEAD_INITIALIZER(hostdevs); 1572b2325ffSGerd Hoffmann 1582b2325ffSGerd Hoffmann static void usb_host_auto_check(void *unused); 1592b2325ffSGerd Hoffmann static void usb_host_release_interfaces(USBHostDevice *s); 1602b2325ffSGerd Hoffmann static void usb_host_nodev(USBHostDevice *s); 161f34d5c75SHans de Goede static void usb_host_detach_kernel(USBHostDevice *s); 1622b2325ffSGerd Hoffmann static void usb_host_attach_kernel(USBHostDevice *s); 1632b2325ffSGerd Hoffmann 1642b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 1652b2325ffSGerd Hoffmann 1661e03e407SChris Johns #ifndef LIBUSB_LOG_LEVEL_WARNING /* older libusb didn't define these */ 1671e03e407SChris Johns #define LIBUSB_LOG_LEVEL_WARNING 2 1681e03e407SChris Johns #endif 1691e03e407SChris Johns 1701e03e407SChris Johns /* ------------------------------------------------------------------------ */ 1711e03e407SChris Johns 1722b2325ffSGerd Hoffmann #define CONTROL_TIMEOUT 10000 /* 10 sec */ 1732b2325ffSGerd Hoffmann #define BULK_TIMEOUT 0 /* unlimited */ 1742b2325ffSGerd Hoffmann #define INTR_TIMEOUT 0 /* unlimited */ 1752b2325ffSGerd Hoffmann 176102a3d84SGerd Hoffmann #ifndef LIBUSB_API_VERSION 177102a3d84SGerd Hoffmann # define LIBUSB_API_VERSION LIBUSBX_API_VERSION 178102a3d84SGerd Hoffmann #endif 179102a3d84SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000103 180322fd1f4SGerd Hoffmann # define HAVE_STREAMS 1 181322fd1f4SGerd Hoffmann #endif 182322fd1f4SGerd Hoffmann 1832b2325ffSGerd Hoffmann static const char *speed_name[] = { 1842b2325ffSGerd Hoffmann [LIBUSB_SPEED_UNKNOWN] = "?", 1852b2325ffSGerd Hoffmann [LIBUSB_SPEED_LOW] = "1.5", 1862b2325ffSGerd Hoffmann [LIBUSB_SPEED_FULL] = "12", 1872b2325ffSGerd Hoffmann [LIBUSB_SPEED_HIGH] = "480", 1882b2325ffSGerd Hoffmann [LIBUSB_SPEED_SUPER] = "5000", 1892b2325ffSGerd Hoffmann }; 1902b2325ffSGerd Hoffmann 1912b2325ffSGerd Hoffmann static const unsigned int speed_map[] = { 1922b2325ffSGerd Hoffmann [LIBUSB_SPEED_LOW] = USB_SPEED_LOW, 1932b2325ffSGerd Hoffmann [LIBUSB_SPEED_FULL] = USB_SPEED_FULL, 1942b2325ffSGerd Hoffmann [LIBUSB_SPEED_HIGH] = USB_SPEED_HIGH, 1952b2325ffSGerd Hoffmann [LIBUSB_SPEED_SUPER] = USB_SPEED_SUPER, 1962b2325ffSGerd Hoffmann }; 1972b2325ffSGerd Hoffmann 1982b2325ffSGerd Hoffmann static const unsigned int status_map[] = { 1992b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_COMPLETED] = USB_RET_SUCCESS, 2002b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_ERROR] = USB_RET_IOERROR, 2012b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_TIMED_OUT] = USB_RET_IOERROR, 2022b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_CANCELLED] = USB_RET_IOERROR, 2032b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_STALL] = USB_RET_STALL, 2042b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_NO_DEVICE] = USB_RET_NODEV, 2052b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_OVERFLOW] = USB_RET_BABBLE, 2062b2325ffSGerd Hoffmann }; 2072b2325ffSGerd Hoffmann 2082b2325ffSGerd Hoffmann static const char *err_names[] = { 2092b2325ffSGerd Hoffmann [-LIBUSB_ERROR_IO] = "IO", 2102b2325ffSGerd Hoffmann [-LIBUSB_ERROR_INVALID_PARAM] = "INVALID_PARAM", 2112b2325ffSGerd Hoffmann [-LIBUSB_ERROR_ACCESS] = "ACCESS", 2122b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NO_DEVICE] = "NO_DEVICE", 2132b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NOT_FOUND] = "NOT_FOUND", 2142b2325ffSGerd Hoffmann [-LIBUSB_ERROR_BUSY] = "BUSY", 2152b2325ffSGerd Hoffmann [-LIBUSB_ERROR_TIMEOUT] = "TIMEOUT", 2162b2325ffSGerd Hoffmann [-LIBUSB_ERROR_OVERFLOW] = "OVERFLOW", 2172b2325ffSGerd Hoffmann [-LIBUSB_ERROR_PIPE] = "PIPE", 2182b2325ffSGerd Hoffmann [-LIBUSB_ERROR_INTERRUPTED] = "INTERRUPTED", 2192b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NO_MEM] = "NO_MEM", 2202b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NOT_SUPPORTED] = "NOT_SUPPORTED", 2212b2325ffSGerd Hoffmann [-LIBUSB_ERROR_OTHER] = "OTHER", 2222b2325ffSGerd Hoffmann }; 2232b2325ffSGerd Hoffmann 2242b2325ffSGerd Hoffmann static libusb_context *ctx; 2252b2325ffSGerd Hoffmann static uint32_t loglevel; 2262b2325ffSGerd Hoffmann 227a277c3e0SStefan Weil #ifndef CONFIG_WIN32 228a277c3e0SStefan Weil 2292b2325ffSGerd Hoffmann static void usb_host_handle_fd(void *opaque) 2302b2325ffSGerd Hoffmann { 2312b2325ffSGerd Hoffmann struct timeval tv = { 0, 0 }; 2322b2325ffSGerd Hoffmann libusb_handle_events_timeout(ctx, &tv); 2332b2325ffSGerd Hoffmann } 2342b2325ffSGerd Hoffmann 2352b2325ffSGerd Hoffmann static void usb_host_add_fd(int fd, short events, void *user_data) 2362b2325ffSGerd Hoffmann { 2372b2325ffSGerd Hoffmann qemu_set_fd_handler(fd, 2382b2325ffSGerd Hoffmann (events & POLLIN) ? usb_host_handle_fd : NULL, 2392b2325ffSGerd Hoffmann (events & POLLOUT) ? usb_host_handle_fd : NULL, 2402b2325ffSGerd Hoffmann ctx); 2412b2325ffSGerd Hoffmann } 2422b2325ffSGerd Hoffmann 2432b2325ffSGerd Hoffmann static void usb_host_del_fd(int fd, void *user_data) 2442b2325ffSGerd Hoffmann { 2452b2325ffSGerd Hoffmann qemu_set_fd_handler(fd, NULL, NULL, NULL); 2462b2325ffSGerd Hoffmann } 2472b2325ffSGerd Hoffmann 248a277c3e0SStefan Weil #endif /* !CONFIG_WIN32 */ 249a277c3e0SStefan Weil 2502b2325ffSGerd Hoffmann static int usb_host_init(void) 2512b2325ffSGerd Hoffmann { 252a277c3e0SStefan Weil #ifndef CONFIG_WIN32 2532b2325ffSGerd Hoffmann const struct libusb_pollfd **poll; 254a277c3e0SStefan Weil #endif 2553bf2b3a1SStefan Weil int rc; 2562b2325ffSGerd Hoffmann 2572b2325ffSGerd Hoffmann if (ctx) { 2582b2325ffSGerd Hoffmann return 0; 2592b2325ffSGerd Hoffmann } 2602b2325ffSGerd Hoffmann rc = libusb_init(&ctx); 2612b2325ffSGerd Hoffmann if (rc != 0) { 2622b2325ffSGerd Hoffmann return -1; 2632b2325ffSGerd Hoffmann } 2649d8fa0dfSJohn Thomson #if LIBUSB_API_VERSION >= 0x01000106 2659d8fa0dfSJohn Thomson libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, loglevel); 2669d8fa0dfSJohn Thomson #else 2672b2325ffSGerd Hoffmann libusb_set_debug(ctx, loglevel); 2689d8fa0dfSJohn Thomson #endif 269a277c3e0SStefan Weil #ifdef CONFIG_WIN32 270a277c3e0SStefan Weil /* FIXME: add support for Windows. */ 271a277c3e0SStefan Weil #else 2722b2325ffSGerd Hoffmann libusb_set_pollfd_notifiers(ctx, usb_host_add_fd, 2732b2325ffSGerd Hoffmann usb_host_del_fd, 2742b2325ffSGerd Hoffmann ctx); 2752b2325ffSGerd Hoffmann poll = libusb_get_pollfds(ctx); 2762b2325ffSGerd Hoffmann if (poll) { 2773bf2b3a1SStefan Weil int i; 2782b2325ffSGerd Hoffmann for (i = 0; poll[i] != NULL; i++) { 2792b2325ffSGerd Hoffmann usb_host_add_fd(poll[i]->fd, poll[i]->events, ctx); 2802b2325ffSGerd Hoffmann } 2812b2325ffSGerd Hoffmann } 2822b2325ffSGerd Hoffmann free(poll); 283a277c3e0SStefan Weil #endif 2842b2325ffSGerd Hoffmann return 0; 2852b2325ffSGerd Hoffmann } 2862b2325ffSGerd Hoffmann 2872b2325ffSGerd Hoffmann static int usb_host_get_port(libusb_device *dev, char *port, size_t len) 2882b2325ffSGerd Hoffmann { 2892b2325ffSGerd Hoffmann uint8_t path[7]; 2902b2325ffSGerd Hoffmann size_t off; 2912b2325ffSGerd Hoffmann int rc, i; 2922b2325ffSGerd Hoffmann 293102a3d84SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000102 294bc45de8cSHans de Goede rc = libusb_get_port_numbers(dev, path, 7); 295bc45de8cSHans de Goede #else 2962b2325ffSGerd Hoffmann rc = libusb_get_port_path(ctx, dev, path, 7); 297bc45de8cSHans de Goede #endif 2982b2325ffSGerd Hoffmann if (rc < 0) { 2992b2325ffSGerd Hoffmann return 0; 3002b2325ffSGerd Hoffmann } 3012b2325ffSGerd Hoffmann off = snprintf(port, len, "%d", path[0]); 3022b2325ffSGerd Hoffmann for (i = 1; i < rc; i++) { 3032b2325ffSGerd Hoffmann off += snprintf(port+off, len-off, ".%d", path[i]); 3042b2325ffSGerd Hoffmann } 3052b2325ffSGerd Hoffmann return off; 3062b2325ffSGerd Hoffmann } 3072b2325ffSGerd Hoffmann 3082b2325ffSGerd Hoffmann static void usb_host_libusb_error(const char *func, int rc) 3092b2325ffSGerd Hoffmann { 3102b2325ffSGerd Hoffmann const char *errname; 3112b2325ffSGerd Hoffmann 3122b2325ffSGerd Hoffmann if (rc >= 0) { 3132b2325ffSGerd Hoffmann return; 3142b2325ffSGerd Hoffmann } 3152b2325ffSGerd Hoffmann 3162b2325ffSGerd Hoffmann if (-rc < ARRAY_SIZE(err_names) && err_names[-rc]) { 3172b2325ffSGerd Hoffmann errname = err_names[-rc]; 3182b2325ffSGerd Hoffmann } else { 3192b2325ffSGerd Hoffmann errname = "?"; 3202b2325ffSGerd Hoffmann } 3212e6a0dd1SGonglei error_report("%s: %d [%s]", func, rc, errname); 3222b2325ffSGerd Hoffmann } 3232b2325ffSGerd Hoffmann 3242b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 3252b2325ffSGerd Hoffmann 3262b2325ffSGerd Hoffmann static bool usb_host_use_combining(USBEndpoint *ep) 3272b2325ffSGerd Hoffmann { 3282b2325ffSGerd Hoffmann int type; 3292b2325ffSGerd Hoffmann 3302b2325ffSGerd Hoffmann if (!ep->pipeline) { 3312b2325ffSGerd Hoffmann return false; 3322b2325ffSGerd Hoffmann } 3332b2325ffSGerd Hoffmann if (ep->pid != USB_TOKEN_IN) { 3342b2325ffSGerd Hoffmann return false; 3352b2325ffSGerd Hoffmann } 3362b2325ffSGerd Hoffmann type = usb_ep_get_type(ep->dev, ep->pid, ep->nr); 3372b2325ffSGerd Hoffmann if (type != USB_ENDPOINT_XFER_BULK) { 3382b2325ffSGerd Hoffmann return false; 3392b2325ffSGerd Hoffmann } 3402b2325ffSGerd Hoffmann return true; 3412b2325ffSGerd Hoffmann } 3422b2325ffSGerd Hoffmann 3432b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 3442b2325ffSGerd Hoffmann 3452b2325ffSGerd Hoffmann static USBHostRequest *usb_host_req_alloc(USBHostDevice *s, USBPacket *p, 3462b2325ffSGerd Hoffmann bool in, size_t bufsize) 3472b2325ffSGerd Hoffmann { 3482b2325ffSGerd Hoffmann USBHostRequest *r = g_new0(USBHostRequest, 1); 3492b2325ffSGerd Hoffmann 3502b2325ffSGerd Hoffmann r->host = s; 3512b2325ffSGerd Hoffmann r->p = p; 3522b2325ffSGerd Hoffmann r->in = in; 3532b2325ffSGerd Hoffmann r->xfer = libusb_alloc_transfer(0); 3542b2325ffSGerd Hoffmann if (bufsize) { 3552b2325ffSGerd Hoffmann r->buffer = g_malloc(bufsize); 3562b2325ffSGerd Hoffmann } 3572b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&s->requests, r, next); 3582b2325ffSGerd Hoffmann return r; 3592b2325ffSGerd Hoffmann } 3602b2325ffSGerd Hoffmann 3612b2325ffSGerd Hoffmann static void usb_host_req_free(USBHostRequest *r) 3622b2325ffSGerd Hoffmann { 3632b2325ffSGerd Hoffmann QTAILQ_REMOVE(&r->host->requests, r, next); 3642b2325ffSGerd Hoffmann libusb_free_transfer(r->xfer); 3652b2325ffSGerd Hoffmann g_free(r->buffer); 3662b2325ffSGerd Hoffmann g_free(r); 3672b2325ffSGerd Hoffmann } 3682b2325ffSGerd Hoffmann 3692b2325ffSGerd Hoffmann static USBHostRequest *usb_host_req_find(USBHostDevice *s, USBPacket *p) 3702b2325ffSGerd Hoffmann { 3712b2325ffSGerd Hoffmann USBHostRequest *r; 3722b2325ffSGerd Hoffmann 3732b2325ffSGerd Hoffmann QTAILQ_FOREACH(r, &s->requests, next) { 3742b2325ffSGerd Hoffmann if (r->p == p) { 3752b2325ffSGerd Hoffmann return r; 3762b2325ffSGerd Hoffmann } 3772b2325ffSGerd Hoffmann } 3782b2325ffSGerd Hoffmann return NULL; 3792b2325ffSGerd Hoffmann } 3802b2325ffSGerd Hoffmann 381c16e3664SStefan Weil static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer) 3822b2325ffSGerd Hoffmann { 3832b2325ffSGerd Hoffmann USBHostRequest *r = xfer->user_data; 3842b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 3852b2325ffSGerd Hoffmann bool disconnect = (xfer->status == LIBUSB_TRANSFER_NO_DEVICE); 3862b2325ffSGerd Hoffmann 3872b2325ffSGerd Hoffmann if (r->p == NULL) { 3882b2325ffSGerd Hoffmann goto out; /* request was canceled */ 3892b2325ffSGerd Hoffmann } 3902b2325ffSGerd Hoffmann 3912b2325ffSGerd Hoffmann r->p->status = status_map[xfer->status]; 3922b2325ffSGerd Hoffmann r->p->actual_length = xfer->actual_length; 3932b2325ffSGerd Hoffmann if (r->in && xfer->actual_length) { 3947bacaf5fSYuri Benditovich USBDevice *udev = USB_DEVICE(s); 3957bacaf5fSYuri Benditovich struct libusb_config_descriptor *conf = (void *)r->cbuf; 3962b2325ffSGerd Hoffmann memcpy(r->cbuf, r->buffer + 8, xfer->actual_length); 397b88a3e01SGerd Hoffmann 398b88a3e01SGerd Hoffmann /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices 399b88a3e01SGerd Hoffmann * to work redirected to a not superspeed capable hcd */ 400b88a3e01SGerd Hoffmann if (r->usb3ep0quirk && xfer->actual_length >= 18 && 401b88a3e01SGerd Hoffmann r->cbuf[7] == 9) { 402b88a3e01SGerd Hoffmann r->cbuf[7] = 64; 403b88a3e01SGerd Hoffmann } 4047bacaf5fSYuri Benditovich /* 4057bacaf5fSYuri Benditovich *If this is GET_DESCRIPTOR request for configuration descriptor, 4067bacaf5fSYuri Benditovich * remove 'remote wakeup' flag from it to prevent idle power down 4077bacaf5fSYuri Benditovich * in Windows guest 4087bacaf5fSYuri Benditovich */ 4097bacaf5fSYuri Benditovich if (s->suppress_remote_wake && 4107bacaf5fSYuri Benditovich udev->setup_buf[0] == USB_DIR_IN && 4117bacaf5fSYuri Benditovich udev->setup_buf[1] == USB_REQ_GET_DESCRIPTOR && 4127bacaf5fSYuri Benditovich udev->setup_buf[3] == USB_DT_CONFIG && udev->setup_buf[2] == 0 && 4137bacaf5fSYuri Benditovich xfer->actual_length > 4147bacaf5fSYuri Benditovich offsetof(struct libusb_config_descriptor, bmAttributes) && 4157bacaf5fSYuri Benditovich (conf->bmAttributes & USB_CFG_ATT_WAKEUP)) { 4167bacaf5fSYuri Benditovich trace_usb_host_remote_wakeup_removed(s->bus_num, s->addr); 4177bacaf5fSYuri Benditovich conf->bmAttributes &= ~USB_CFG_ATT_WAKEUP; 4187bacaf5fSYuri Benditovich } 4192b2325ffSGerd Hoffmann } 4202b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 4212b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 4222b2325ffSGerd Hoffmann usb_generic_async_ctrl_complete(USB_DEVICE(s), r->p); 4232b2325ffSGerd Hoffmann 4242b2325ffSGerd Hoffmann out: 4252b2325ffSGerd Hoffmann usb_host_req_free(r); 4262b2325ffSGerd Hoffmann if (disconnect) { 4272b2325ffSGerd Hoffmann usb_host_nodev(s); 4282b2325ffSGerd Hoffmann } 4292b2325ffSGerd Hoffmann } 4302b2325ffSGerd Hoffmann 431c16e3664SStefan Weil static void LIBUSB_CALL usb_host_req_complete_data(struct libusb_transfer *xfer) 4322b2325ffSGerd Hoffmann { 4332b2325ffSGerd Hoffmann USBHostRequest *r = xfer->user_data; 4342b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 4352b2325ffSGerd Hoffmann bool disconnect = (xfer->status == LIBUSB_TRANSFER_NO_DEVICE); 4362b2325ffSGerd Hoffmann 4372b2325ffSGerd Hoffmann if (r->p == NULL) { 4382b2325ffSGerd Hoffmann goto out; /* request was canceled */ 4392b2325ffSGerd Hoffmann } 4402b2325ffSGerd Hoffmann 4412b2325ffSGerd Hoffmann r->p->status = status_map[xfer->status]; 4422b2325ffSGerd Hoffmann if (r->in && xfer->actual_length) { 4432b2325ffSGerd Hoffmann usb_packet_copy(r->p, r->buffer, xfer->actual_length); 4442b2325ffSGerd Hoffmann } 4452b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 4462b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 4472b2325ffSGerd Hoffmann if (usb_host_use_combining(r->p->ep)) { 4482b2325ffSGerd Hoffmann usb_combined_input_packet_complete(USB_DEVICE(s), r->p); 4492b2325ffSGerd Hoffmann } else { 4502b2325ffSGerd Hoffmann usb_packet_complete(USB_DEVICE(s), r->p); 4512b2325ffSGerd Hoffmann } 4522b2325ffSGerd Hoffmann 4532b2325ffSGerd Hoffmann out: 4542b2325ffSGerd Hoffmann usb_host_req_free(r); 4552b2325ffSGerd Hoffmann if (disconnect) { 4562b2325ffSGerd Hoffmann usb_host_nodev(s); 4572b2325ffSGerd Hoffmann } 4582b2325ffSGerd Hoffmann } 4592b2325ffSGerd Hoffmann 4602b2325ffSGerd Hoffmann static void usb_host_req_abort(USBHostRequest *r) 4612b2325ffSGerd Hoffmann { 4622b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 46345ec2671SEd Maste bool inflight = (r->p && r->p->state == USB_PACKET_ASYNC); 4642b2325ffSGerd Hoffmann 4652b2325ffSGerd Hoffmann if (inflight) { 4662b2325ffSGerd Hoffmann r->p->status = USB_RET_NODEV; 4672b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 4682b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 4692b2325ffSGerd Hoffmann if (r->p->ep->nr == 0) { 4702b2325ffSGerd Hoffmann usb_generic_async_ctrl_complete(USB_DEVICE(s), r->p); 4712b2325ffSGerd Hoffmann } else { 4722b2325ffSGerd Hoffmann usb_packet_complete(USB_DEVICE(s), r->p); 4732b2325ffSGerd Hoffmann } 4742b2325ffSGerd Hoffmann r->p = NULL; 4752b2325ffSGerd Hoffmann 4762b2325ffSGerd Hoffmann libusb_cancel_transfer(r->xfer); 4772b2325ffSGerd Hoffmann } 4782b2325ffSGerd Hoffmann } 4792b2325ffSGerd Hoffmann 4802b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 4812b2325ffSGerd Hoffmann 482c16e3664SStefan Weil static void LIBUSB_CALL 483c16e3664SStefan Weil usb_host_req_complete_iso(struct libusb_transfer *transfer) 4842b2325ffSGerd Hoffmann { 4852b2325ffSGerd Hoffmann USBHostIsoXfer *xfer = transfer->user_data; 4862b2325ffSGerd Hoffmann 4872b2325ffSGerd Hoffmann if (!xfer) { 4882b2325ffSGerd Hoffmann /* USBHostIsoXfer released while inflight */ 4892b2325ffSGerd Hoffmann g_free(transfer->buffer); 4902b2325ffSGerd Hoffmann libusb_free_transfer(transfer); 4912b2325ffSGerd Hoffmann return; 4922b2325ffSGerd Hoffmann } 4932b2325ffSGerd Hoffmann 4942b2325ffSGerd Hoffmann QTAILQ_REMOVE(&xfer->ring->inflight, xfer, next); 4952b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&xfer->ring->inflight)) { 4962b2325ffSGerd Hoffmann USBHostDevice *s = xfer->ring->host; 4972b2325ffSGerd Hoffmann trace_usb_host_iso_stop(s->bus_num, s->addr, xfer->ring->ep->nr); 4982b2325ffSGerd Hoffmann } 4992b2325ffSGerd Hoffmann if (xfer->ring->ep->pid == USB_TOKEN_IN) { 5002b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&xfer->ring->copy, xfer, next); 501e206ddfbSGerd Hoffmann usb_wakeup(xfer->ring->ep, 0); 5022b2325ffSGerd Hoffmann } else { 5032b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&xfer->ring->unused, xfer, next); 5042b2325ffSGerd Hoffmann } 5052b2325ffSGerd Hoffmann } 5062b2325ffSGerd Hoffmann 5072b2325ffSGerd Hoffmann static USBHostIsoRing *usb_host_iso_alloc(USBHostDevice *s, USBEndpoint *ep) 5082b2325ffSGerd Hoffmann { 5092b2325ffSGerd Hoffmann USBHostIsoRing *ring = g_new0(USBHostIsoRing, 1); 5102b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 5112b2325ffSGerd Hoffmann /* FIXME: check interval (for now assume one xfer per frame) */ 5122b2325ffSGerd Hoffmann int packets = s->iso_urb_frames; 5132b2325ffSGerd Hoffmann int i; 5142b2325ffSGerd Hoffmann 5152b2325ffSGerd Hoffmann ring->host = s; 5162b2325ffSGerd Hoffmann ring->ep = ep; 5172b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->unused); 5182b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->inflight); 5192b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->copy); 5202b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&s->isorings, ring, next); 5212b2325ffSGerd Hoffmann 5222b2325ffSGerd Hoffmann for (i = 0; i < s->iso_urb_count; i++) { 5232b2325ffSGerd Hoffmann xfer = g_new0(USBHostIsoXfer, 1); 5242b2325ffSGerd Hoffmann xfer->ring = ring; 5252b2325ffSGerd Hoffmann xfer->xfer = libusb_alloc_transfer(packets); 5262b2325ffSGerd Hoffmann xfer->xfer->dev_handle = s->dh; 5272b2325ffSGerd Hoffmann xfer->xfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; 5282b2325ffSGerd Hoffmann 5292b2325ffSGerd Hoffmann xfer->xfer->endpoint = ring->ep->nr; 5302b2325ffSGerd Hoffmann if (ring->ep->pid == USB_TOKEN_IN) { 5312b2325ffSGerd Hoffmann xfer->xfer->endpoint |= USB_DIR_IN; 5322b2325ffSGerd Hoffmann } 5332b2325ffSGerd Hoffmann xfer->xfer->callback = usb_host_req_complete_iso; 5342b2325ffSGerd Hoffmann xfer->xfer->user_data = xfer; 5352b2325ffSGerd Hoffmann 5362b2325ffSGerd Hoffmann xfer->xfer->num_iso_packets = packets; 5372b2325ffSGerd Hoffmann xfer->xfer->length = ring->ep->max_packet_size * packets; 5382b2325ffSGerd Hoffmann xfer->xfer->buffer = g_malloc0(xfer->xfer->length); 5392b2325ffSGerd Hoffmann 5402b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 5412b2325ffSGerd Hoffmann } 5422b2325ffSGerd Hoffmann 5432b2325ffSGerd Hoffmann return ring; 5442b2325ffSGerd Hoffmann } 5452b2325ffSGerd Hoffmann 5462b2325ffSGerd Hoffmann static USBHostIsoRing *usb_host_iso_find(USBHostDevice *s, USBEndpoint *ep) 5472b2325ffSGerd Hoffmann { 5482b2325ffSGerd Hoffmann USBHostIsoRing *ring; 5492b2325ffSGerd Hoffmann 5502b2325ffSGerd Hoffmann QTAILQ_FOREACH(ring, &s->isorings, next) { 5512b2325ffSGerd Hoffmann if (ring->ep == ep) { 5522b2325ffSGerd Hoffmann return ring; 5532b2325ffSGerd Hoffmann } 5542b2325ffSGerd Hoffmann } 5552b2325ffSGerd Hoffmann return NULL; 5562b2325ffSGerd Hoffmann } 5572b2325ffSGerd Hoffmann 5582b2325ffSGerd Hoffmann static void usb_host_iso_reset_xfer(USBHostIsoXfer *xfer) 5592b2325ffSGerd Hoffmann { 5602b2325ffSGerd Hoffmann libusb_set_iso_packet_lengths(xfer->xfer, 5612b2325ffSGerd Hoffmann xfer->ring->ep->max_packet_size); 5622b2325ffSGerd Hoffmann xfer->packet = 0; 5632b2325ffSGerd Hoffmann xfer->copy_complete = false; 5642b2325ffSGerd Hoffmann } 5652b2325ffSGerd Hoffmann 5662b2325ffSGerd Hoffmann static void usb_host_iso_free_xfer(USBHostIsoXfer *xfer, bool inflight) 5672b2325ffSGerd Hoffmann { 5682b2325ffSGerd Hoffmann if (inflight) { 5692b2325ffSGerd Hoffmann xfer->xfer->user_data = NULL; 5702b2325ffSGerd Hoffmann } else { 5712b2325ffSGerd Hoffmann g_free(xfer->xfer->buffer); 5722b2325ffSGerd Hoffmann libusb_free_transfer(xfer->xfer); 5732b2325ffSGerd Hoffmann } 5742b2325ffSGerd Hoffmann g_free(xfer); 5752b2325ffSGerd Hoffmann } 5762b2325ffSGerd Hoffmann 5772b2325ffSGerd Hoffmann static void usb_host_iso_free(USBHostIsoRing *ring) 5782b2325ffSGerd Hoffmann { 5792b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 5802b2325ffSGerd Hoffmann 5812b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->inflight)) != NULL) { 5822b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->inflight, xfer, next); 5832b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, true); 5842b2325ffSGerd Hoffmann } 5852b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->unused)) != NULL) { 5862b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 5872b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, false); 5882b2325ffSGerd Hoffmann } 5892b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->copy)) != NULL) { 5902b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 5912b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, false); 5922b2325ffSGerd Hoffmann } 5932b2325ffSGerd Hoffmann 5942b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->host->isorings, ring, next); 5952b2325ffSGerd Hoffmann g_free(ring); 5962b2325ffSGerd Hoffmann } 5972b2325ffSGerd Hoffmann 5982b2325ffSGerd Hoffmann static void usb_host_iso_free_all(USBHostDevice *s) 5992b2325ffSGerd Hoffmann { 6002b2325ffSGerd Hoffmann USBHostIsoRing *ring; 6012b2325ffSGerd Hoffmann 6022b2325ffSGerd Hoffmann while ((ring = QTAILQ_FIRST(&s->isorings)) != NULL) { 6032b2325ffSGerd Hoffmann usb_host_iso_free(ring); 6042b2325ffSGerd Hoffmann } 6052b2325ffSGerd Hoffmann } 6062b2325ffSGerd Hoffmann 6072b2325ffSGerd Hoffmann static bool usb_host_iso_data_copy(USBHostIsoXfer *xfer, USBPacket *p) 6082b2325ffSGerd Hoffmann { 6092b2325ffSGerd Hoffmann unsigned int psize; 6102b2325ffSGerd Hoffmann unsigned char *buf; 6112b2325ffSGerd Hoffmann 6122b2325ffSGerd Hoffmann buf = libusb_get_iso_packet_buffer_simple(xfer->xfer, xfer->packet); 6132b2325ffSGerd Hoffmann if (p->pid == USB_TOKEN_OUT) { 6142b2325ffSGerd Hoffmann psize = p->iov.size; 6152b2325ffSGerd Hoffmann if (psize > xfer->ring->ep->max_packet_size) { 6162b2325ffSGerd Hoffmann /* should not happen (guest bug) */ 6172b2325ffSGerd Hoffmann psize = xfer->ring->ep->max_packet_size; 6182b2325ffSGerd Hoffmann } 6192b2325ffSGerd Hoffmann xfer->xfer->iso_packet_desc[xfer->packet].length = psize; 6202b2325ffSGerd Hoffmann } else { 6212b2325ffSGerd Hoffmann psize = xfer->xfer->iso_packet_desc[xfer->packet].actual_length; 6222b2325ffSGerd Hoffmann if (psize > p->iov.size) { 6232b2325ffSGerd Hoffmann /* should not happen (guest bug) */ 6242b2325ffSGerd Hoffmann psize = p->iov.size; 6252b2325ffSGerd Hoffmann } 6262b2325ffSGerd Hoffmann } 6272b2325ffSGerd Hoffmann usb_packet_copy(p, buf, psize); 6282b2325ffSGerd Hoffmann xfer->packet++; 6292b2325ffSGerd Hoffmann xfer->copy_complete = (xfer->packet == xfer->xfer->num_iso_packets); 6302b2325ffSGerd Hoffmann return xfer->copy_complete; 6312b2325ffSGerd Hoffmann } 6322b2325ffSGerd Hoffmann 6332b2325ffSGerd Hoffmann static void usb_host_iso_data_in(USBHostDevice *s, USBPacket *p) 6342b2325ffSGerd Hoffmann { 6352b2325ffSGerd Hoffmann USBHostIsoRing *ring; 6362b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 6372b2325ffSGerd Hoffmann bool disconnect = false; 6382b2325ffSGerd Hoffmann int rc; 6392b2325ffSGerd Hoffmann 6402b2325ffSGerd Hoffmann ring = usb_host_iso_find(s, p->ep); 6412b2325ffSGerd Hoffmann if (ring == NULL) { 6422b2325ffSGerd Hoffmann ring = usb_host_iso_alloc(s, p->ep); 6432b2325ffSGerd Hoffmann } 6442b2325ffSGerd Hoffmann 6452b2325ffSGerd Hoffmann /* copy data to guest */ 6462b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->copy); 6472b2325ffSGerd Hoffmann if (xfer != NULL) { 6482b2325ffSGerd Hoffmann if (usb_host_iso_data_copy(xfer, p)) { 6492b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 6502b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 6512b2325ffSGerd Hoffmann } 6522b2325ffSGerd Hoffmann } 6532b2325ffSGerd Hoffmann 6542b2325ffSGerd Hoffmann /* submit empty bufs to host */ 6552b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->unused)) != NULL) { 6562b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 6572b2325ffSGerd Hoffmann usb_host_iso_reset_xfer(xfer); 6582b2325ffSGerd Hoffmann rc = libusb_submit_transfer(xfer->xfer); 6592b2325ffSGerd Hoffmann if (rc != 0) { 6602b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_submit_transfer [iso]", rc); 6612b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 6622b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 6632b2325ffSGerd Hoffmann disconnect = true; 6642b2325ffSGerd Hoffmann } 6652b2325ffSGerd Hoffmann break; 6662b2325ffSGerd Hoffmann } 6672b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 6682b2325ffSGerd Hoffmann trace_usb_host_iso_start(s->bus_num, s->addr, p->ep->nr); 6692b2325ffSGerd Hoffmann } 6702b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->inflight, xfer, next); 6712b2325ffSGerd Hoffmann } 6722b2325ffSGerd Hoffmann 6732b2325ffSGerd Hoffmann if (disconnect) { 6742b2325ffSGerd Hoffmann usb_host_nodev(s); 6752b2325ffSGerd Hoffmann } 6762b2325ffSGerd Hoffmann } 6772b2325ffSGerd Hoffmann 6782b2325ffSGerd Hoffmann static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p) 6792b2325ffSGerd Hoffmann { 6802b2325ffSGerd Hoffmann USBHostIsoRing *ring; 6812b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 6822b2325ffSGerd Hoffmann bool disconnect = false; 6832b2325ffSGerd Hoffmann int rc, filled = 0; 6842b2325ffSGerd Hoffmann 6852b2325ffSGerd Hoffmann ring = usb_host_iso_find(s, p->ep); 6862b2325ffSGerd Hoffmann if (ring == NULL) { 6872b2325ffSGerd Hoffmann ring = usb_host_iso_alloc(s, p->ep); 6882b2325ffSGerd Hoffmann } 6892b2325ffSGerd Hoffmann 6902b2325ffSGerd Hoffmann /* copy data from guest */ 6912b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->copy); 6922b2325ffSGerd Hoffmann while (xfer != NULL && xfer->copy_complete) { 6932b2325ffSGerd Hoffmann filled++; 6942b2325ffSGerd Hoffmann xfer = QTAILQ_NEXT(xfer, next); 6952b2325ffSGerd Hoffmann } 6962b2325ffSGerd Hoffmann if (xfer == NULL) { 6972b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->unused); 6982b2325ffSGerd Hoffmann if (xfer == NULL) { 6992b2325ffSGerd Hoffmann trace_usb_host_iso_out_of_bufs(s->bus_num, s->addr, p->ep->nr); 7002b2325ffSGerd Hoffmann return; 7012b2325ffSGerd Hoffmann } 7022b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 7032b2325ffSGerd Hoffmann usb_host_iso_reset_xfer(xfer); 7042b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->copy, xfer, next); 7052b2325ffSGerd Hoffmann } 7062b2325ffSGerd Hoffmann usb_host_iso_data_copy(xfer, p); 7072b2325ffSGerd Hoffmann 7082b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 7092b2325ffSGerd Hoffmann /* wait until half of our buffers are filled 7102b2325ffSGerd Hoffmann before kicking the iso out stream */ 7112b2325ffSGerd Hoffmann if (filled*2 < s->iso_urb_count) { 7122b2325ffSGerd Hoffmann return; 7132b2325ffSGerd Hoffmann } 7142b2325ffSGerd Hoffmann } 7152b2325ffSGerd Hoffmann 7162b2325ffSGerd Hoffmann /* submit filled bufs to host */ 7172b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->copy)) != NULL && 7182b2325ffSGerd Hoffmann xfer->copy_complete) { 7192b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 7202b2325ffSGerd Hoffmann rc = libusb_submit_transfer(xfer->xfer); 7212b2325ffSGerd Hoffmann if (rc != 0) { 7222b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_submit_transfer [iso]", rc); 7232b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 7242b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 7252b2325ffSGerd Hoffmann disconnect = true; 7262b2325ffSGerd Hoffmann } 7272b2325ffSGerd Hoffmann break; 7282b2325ffSGerd Hoffmann } 7292b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 7302b2325ffSGerd Hoffmann trace_usb_host_iso_start(s->bus_num, s->addr, p->ep->nr); 7312b2325ffSGerd Hoffmann } 7322b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->inflight, xfer, next); 7332b2325ffSGerd Hoffmann } 7342b2325ffSGerd Hoffmann 7352b2325ffSGerd Hoffmann if (disconnect) { 7362b2325ffSGerd Hoffmann usb_host_nodev(s); 7372b2325ffSGerd Hoffmann } 7382b2325ffSGerd Hoffmann } 7392b2325ffSGerd Hoffmann 7402b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 7412b2325ffSGerd Hoffmann 742b88a3e01SGerd Hoffmann static void usb_host_speed_compat(USBHostDevice *s) 743c3268cc1SGerd Hoffmann { 744b88a3e01SGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 745c3268cc1SGerd Hoffmann struct libusb_config_descriptor *conf; 746c3268cc1SGerd Hoffmann const struct libusb_interface_descriptor *intf; 747c3268cc1SGerd Hoffmann const struct libusb_endpoint_descriptor *endp; 748322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 749b88a3e01SGerd Hoffmann struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp; 750b88a3e01SGerd Hoffmann #endif 751b88a3e01SGerd Hoffmann bool compat_high = true; 752b88a3e01SGerd Hoffmann bool compat_full = true; 753c3268cc1SGerd Hoffmann uint8_t type; 754c3268cc1SGerd Hoffmann int rc, c, i, a, e; 755c3268cc1SGerd Hoffmann 756c3268cc1SGerd Hoffmann for (c = 0;; c++) { 757c3268cc1SGerd Hoffmann rc = libusb_get_config_descriptor(s->dev, c, &conf); 758c3268cc1SGerd Hoffmann if (rc != 0) { 759c3268cc1SGerd Hoffmann break; 760c3268cc1SGerd Hoffmann } 761c3268cc1SGerd Hoffmann for (i = 0; i < conf->bNumInterfaces; i++) { 762c3268cc1SGerd Hoffmann for (a = 0; a < conf->interface[i].num_altsetting; a++) { 763c3268cc1SGerd Hoffmann intf = &conf->interface[i].altsetting[a]; 764c3268cc1SGerd Hoffmann for (e = 0; e < intf->bNumEndpoints; e++) { 765c3268cc1SGerd Hoffmann endp = &intf->endpoint[e]; 766c3268cc1SGerd Hoffmann type = endp->bmAttributes & 0x3; 767c3268cc1SGerd Hoffmann switch (type) { 768c3268cc1SGerd Hoffmann case 0x01: /* ISO */ 769b88a3e01SGerd Hoffmann compat_full = false; 770b88a3e01SGerd Hoffmann compat_high = false; 771b88a3e01SGerd Hoffmann break; 772b88a3e01SGerd Hoffmann case 0x02: /* BULK */ 773322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 774b88a3e01SGerd Hoffmann rc = libusb_get_ss_endpoint_companion_descriptor 775b88a3e01SGerd Hoffmann (ctx, endp, &endp_ss_comp); 776b88a3e01SGerd Hoffmann if (rc == LIBUSB_SUCCESS) { 7776a711234SGerd Hoffmann int streams = endp_ss_comp->bmAttributes & 0x1f; 7786a711234SGerd Hoffmann if (streams) { 779b88a3e01SGerd Hoffmann compat_full = false; 780b88a3e01SGerd Hoffmann compat_high = false; 781b88a3e01SGerd Hoffmann } 7826a711234SGerd Hoffmann libusb_free_ss_endpoint_companion_descriptor 7836a711234SGerd Hoffmann (endp_ss_comp); 7846a711234SGerd Hoffmann } 785b88a3e01SGerd Hoffmann #endif 786b88a3e01SGerd Hoffmann break; 787c3268cc1SGerd Hoffmann case 0x03: /* INTERRUPT */ 788c3268cc1SGerd Hoffmann if (endp->wMaxPacketSize > 64) { 789b88a3e01SGerd Hoffmann compat_full = false; 790b88a3e01SGerd Hoffmann } 791b88a3e01SGerd Hoffmann if (endp->wMaxPacketSize > 1024) { 792b88a3e01SGerd Hoffmann compat_high = false; 793c3268cc1SGerd Hoffmann } 794c3268cc1SGerd Hoffmann break; 795c3268cc1SGerd Hoffmann } 796c3268cc1SGerd Hoffmann } 797c3268cc1SGerd Hoffmann } 798c3268cc1SGerd Hoffmann } 799c3268cc1SGerd Hoffmann libusb_free_config_descriptor(conf); 800c3268cc1SGerd Hoffmann } 801b88a3e01SGerd Hoffmann 802b88a3e01SGerd Hoffmann udev->speedmask = (1 << udev->speed); 803b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_SUPER && compat_high) { 80479ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_HIGH; 805b88a3e01SGerd Hoffmann } 806b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_SUPER && compat_full) { 80779ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_FULL; 808b88a3e01SGerd Hoffmann } 809b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_HIGH && compat_full) { 81079ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_FULL; 811b88a3e01SGerd Hoffmann } 812c3268cc1SGerd Hoffmann } 813c3268cc1SGerd Hoffmann 8142b2325ffSGerd Hoffmann static void usb_host_ep_update(USBHostDevice *s) 8152b2325ffSGerd Hoffmann { 8162b2325ffSGerd Hoffmann static const char *tname[] = { 8172b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_CONTROL] = "control", 8182b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_ISOC] = "isoc", 8192b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_BULK] = "bulk", 8202b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_INT] = "int", 8212b2325ffSGerd Hoffmann }; 8222b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 8232b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 8242b2325ffSGerd Hoffmann const struct libusb_interface_descriptor *intf; 8252b2325ffSGerd Hoffmann const struct libusb_endpoint_descriptor *endp; 826322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 827b664b80fSHans de Goede struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp; 828b664b80fSHans de Goede #endif 8292b2325ffSGerd Hoffmann uint8_t devep, type; 8302b2325ffSGerd Hoffmann int pid, ep; 8312b2325ffSGerd Hoffmann int rc, i, e; 8322b2325ffSGerd Hoffmann 8332b2325ffSGerd Hoffmann usb_ep_reset(udev); 8342b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 8352b2325ffSGerd Hoffmann if (rc != 0) { 8362b2325ffSGerd Hoffmann return; 8372b2325ffSGerd Hoffmann } 8382b2325ffSGerd Hoffmann trace_usb_host_parse_config(s->bus_num, s->addr, 8392b2325ffSGerd Hoffmann conf->bConfigurationValue, true); 8402b2325ffSGerd Hoffmann 8412b2325ffSGerd Hoffmann for (i = 0; i < conf->bNumInterfaces; i++) { 8422b2325ffSGerd Hoffmann assert(udev->altsetting[i] < conf->interface[i].num_altsetting); 8432b2325ffSGerd Hoffmann intf = &conf->interface[i].altsetting[udev->altsetting[i]]; 8442b2325ffSGerd Hoffmann trace_usb_host_parse_interface(s->bus_num, s->addr, 8452b2325ffSGerd Hoffmann intf->bInterfaceNumber, 8462b2325ffSGerd Hoffmann intf->bAlternateSetting, true); 8472b2325ffSGerd Hoffmann for (e = 0; e < intf->bNumEndpoints; e++) { 8482b2325ffSGerd Hoffmann endp = &intf->endpoint[e]; 8492b2325ffSGerd Hoffmann 8502b2325ffSGerd Hoffmann devep = endp->bEndpointAddress; 8512b2325ffSGerd Hoffmann pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; 8522b2325ffSGerd Hoffmann ep = devep & 0xf; 8532b2325ffSGerd Hoffmann type = endp->bmAttributes & 0x3; 8542b2325ffSGerd Hoffmann 8552b2325ffSGerd Hoffmann if (ep == 0) { 8562b2325ffSGerd Hoffmann trace_usb_host_parse_error(s->bus_num, s->addr, 8572b2325ffSGerd Hoffmann "invalid endpoint address"); 8582b2325ffSGerd Hoffmann return; 8592b2325ffSGerd Hoffmann } 8602b2325ffSGerd Hoffmann if (usb_ep_get_type(udev, pid, ep) != USB_ENDPOINT_XFER_INVALID) { 8612b2325ffSGerd Hoffmann trace_usb_host_parse_error(s->bus_num, s->addr, 8622b2325ffSGerd Hoffmann "duplicate endpoint address"); 8632b2325ffSGerd Hoffmann return; 8642b2325ffSGerd Hoffmann } 8652b2325ffSGerd Hoffmann 8662b2325ffSGerd Hoffmann trace_usb_host_parse_endpoint(s->bus_num, s->addr, ep, 8672b2325ffSGerd Hoffmann (devep & USB_DIR_IN) ? "in" : "out", 8682b2325ffSGerd Hoffmann tname[type], true); 8692b2325ffSGerd Hoffmann usb_ep_set_max_packet_size(udev, pid, ep, 8702b2325ffSGerd Hoffmann endp->wMaxPacketSize); 8712b2325ffSGerd Hoffmann usb_ep_set_type(udev, pid, ep, type); 8722b2325ffSGerd Hoffmann usb_ep_set_ifnum(udev, pid, ep, i); 8732b2325ffSGerd Hoffmann usb_ep_set_halted(udev, pid, ep, 0); 874322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 875b664b80fSHans de Goede if (type == LIBUSB_TRANSFER_TYPE_BULK && 876b664b80fSHans de Goede libusb_get_ss_endpoint_companion_descriptor(ctx, endp, 877b664b80fSHans de Goede &endp_ss_comp) == LIBUSB_SUCCESS) { 878b664b80fSHans de Goede usb_ep_set_max_streams(udev, pid, ep, 879b664b80fSHans de Goede endp_ss_comp->bmAttributes); 880b664b80fSHans de Goede libusb_free_ss_endpoint_companion_descriptor(endp_ss_comp); 881b664b80fSHans de Goede } 882b664b80fSHans de Goede #endif 8832b2325ffSGerd Hoffmann } 8842b2325ffSGerd Hoffmann } 8852b2325ffSGerd Hoffmann 8862b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 8872b2325ffSGerd Hoffmann } 8882b2325ffSGerd Hoffmann 8899f815e83SGerd Hoffmann static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) 8902b2325ffSGerd Hoffmann { 8912b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 892202d69a7SGerd Hoffmann int libusb_speed; 8939f815e83SGerd Hoffmann int bus_num = 0; 8949f815e83SGerd Hoffmann int addr = 0; 8952b2325ffSGerd Hoffmann int rc; 8967d553f27SGonglei Error *local_err = NULL; 8972b2325ffSGerd Hoffmann 8983280ea8eSGerd Hoffmann if (s->bh_postld_pending) { 8993280ea8eSGerd Hoffmann return -1; 9003280ea8eSGerd Hoffmann } 9012b2325ffSGerd Hoffmann if (s->dh != NULL) { 9022b2325ffSGerd Hoffmann goto fail; 9032b2325ffSGerd Hoffmann } 9049f815e83SGerd Hoffmann 9059f815e83SGerd Hoffmann if (dev) { 9069f815e83SGerd Hoffmann bus_num = libusb_get_bus_number(dev); 9079f815e83SGerd Hoffmann addr = libusb_get_device_address(dev); 9089f815e83SGerd Hoffmann trace_usb_host_open_started(bus_num, addr); 9099f815e83SGerd Hoffmann 9102b2325ffSGerd Hoffmann rc = libusb_open(dev, &s->dh); 9112b2325ffSGerd Hoffmann if (rc != 0) { 9122b2325ffSGerd Hoffmann goto fail; 9132b2325ffSGerd Hoffmann } 9149f815e83SGerd Hoffmann } else { 915631009e7SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) 9169f815e83SGerd Hoffmann trace_usb_host_open_hostfd(hostfd); 9179f815e83SGerd Hoffmann 9189f815e83SGerd Hoffmann rc = libusb_wrap_sys_device(ctx, hostfd, &s->dh); 9199f815e83SGerd Hoffmann if (rc != 0) { 9209f815e83SGerd Hoffmann goto fail; 9219f815e83SGerd Hoffmann } 9229f815e83SGerd Hoffmann s->hostfd = hostfd; 9239f815e83SGerd Hoffmann dev = libusb_get_device(s->dh); 9249f815e83SGerd Hoffmann bus_num = libusb_get_bus_number(dev); 9259f815e83SGerd Hoffmann addr = libusb_get_device_address(dev); 9269f815e83SGerd Hoffmann #else 9279f815e83SGerd Hoffmann g_assert_not_reached(); 9289f815e83SGerd Hoffmann #endif 9299f815e83SGerd Hoffmann } 9302b2325ffSGerd Hoffmann 9312b2325ffSGerd Hoffmann s->dev = dev; 9322b2325ffSGerd Hoffmann s->bus_num = bus_num; 9332b2325ffSGerd Hoffmann s->addr = addr; 934f34d5c75SHans de Goede 935f34d5c75SHans de Goede usb_host_detach_kernel(s); 936f34d5c75SHans de Goede 937f34d5c75SHans de Goede libusb_get_device_descriptor(dev, &s->ddesc); 9382b2325ffSGerd Hoffmann usb_host_get_port(s->dev, s->port, sizeof(s->port)); 9392b2325ffSGerd Hoffmann 9402b2325ffSGerd Hoffmann usb_ep_init(udev); 9412b2325ffSGerd Hoffmann usb_host_ep_update(s); 9422b2325ffSGerd Hoffmann 943202d69a7SGerd Hoffmann libusb_speed = libusb_get_device_speed(dev); 944*a3c27ea0SFabrice Fontaine #if LIBUSB_API_VERSION >= 0x01000107 && defined(CONFIG_LINUX) && \ 945*a3c27ea0SFabrice Fontaine defined(USBDEVFS_GET_SPEED) 946202d69a7SGerd Hoffmann if (hostfd && libusb_speed == 0) { 947202d69a7SGerd Hoffmann /* 948202d69a7SGerd Hoffmann * Workaround libusb bug: libusb_get_device_speed() does not 949202d69a7SGerd Hoffmann * work for libusb_wrap_sys_device() devices in v1.0.23. 950202d69a7SGerd Hoffmann * 951202d69a7SGerd Hoffmann * Speeds are defined in linux/usb/ch9.h, file not included 952202d69a7SGerd Hoffmann * due to name conflicts. 953202d69a7SGerd Hoffmann */ 954202d69a7SGerd Hoffmann int rc = ioctl(hostfd, USBDEVFS_GET_SPEED, NULL); 955202d69a7SGerd Hoffmann switch (rc) { 956202d69a7SGerd Hoffmann case 1: /* low */ 957202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_LOW; 958202d69a7SGerd Hoffmann break; 959202d69a7SGerd Hoffmann case 2: /* full */ 960202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_FULL; 961202d69a7SGerd Hoffmann break; 962202d69a7SGerd Hoffmann case 3: /* high */ 963202d69a7SGerd Hoffmann case 4: /* wireless */ 964202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_HIGH; 965202d69a7SGerd Hoffmann break; 966202d69a7SGerd Hoffmann case 5: /* super */ 967202d69a7SGerd Hoffmann case 6: /* super plus */ 968202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_SUPER; 969202d69a7SGerd Hoffmann break; 970202d69a7SGerd Hoffmann } 971202d69a7SGerd Hoffmann } 972202d69a7SGerd Hoffmann #endif 973202d69a7SGerd Hoffmann udev->speed = speed_map[libusb_speed]; 974b88a3e01SGerd Hoffmann usb_host_speed_compat(s); 9752b2325ffSGerd Hoffmann 9762b2325ffSGerd Hoffmann if (s->ddesc.iProduct) { 9772b2325ffSGerd Hoffmann libusb_get_string_descriptor_ascii(s->dh, s->ddesc.iProduct, 9782b2325ffSGerd Hoffmann (unsigned char *)udev->product_desc, 9792b2325ffSGerd Hoffmann sizeof(udev->product_desc)); 9802b2325ffSGerd Hoffmann } else { 9812b2325ffSGerd Hoffmann snprintf(udev->product_desc, sizeof(udev->product_desc), 9822b2325ffSGerd Hoffmann "host:%d.%d", bus_num, addr); 9832b2325ffSGerd Hoffmann } 9842b2325ffSGerd Hoffmann 9857d553f27SGonglei usb_device_attach(udev, &local_err); 9867d553f27SGonglei if (local_err) { 987565f65d2SMarkus Armbruster error_report_err(local_err); 9882b2325ffSGerd Hoffmann goto fail; 9892b2325ffSGerd Hoffmann } 9902b2325ffSGerd Hoffmann 9912b2325ffSGerd Hoffmann trace_usb_host_open_success(bus_num, addr); 9922b2325ffSGerd Hoffmann return 0; 9932b2325ffSGerd Hoffmann 9942b2325ffSGerd Hoffmann fail: 9952b2325ffSGerd Hoffmann trace_usb_host_open_failure(bus_num, addr); 9962b2325ffSGerd Hoffmann if (s->dh != NULL) { 9976110ce59SLin Ma usb_host_release_interfaces(s); 9986110ce59SLin Ma libusb_reset_device(s->dh); 9996110ce59SLin Ma usb_host_attach_kernel(s); 10002b2325ffSGerd Hoffmann libusb_close(s->dh); 10012b2325ffSGerd Hoffmann s->dh = NULL; 10022b2325ffSGerd Hoffmann s->dev = NULL; 10032b2325ffSGerd Hoffmann } 10042b2325ffSGerd Hoffmann return -1; 10052b2325ffSGerd Hoffmann } 10062b2325ffSGerd Hoffmann 10072b2325ffSGerd Hoffmann static void usb_host_abort_xfers(USBHostDevice *s) 10082b2325ffSGerd Hoffmann { 10092b2325ffSGerd Hoffmann USBHostRequest *r, *rtmp; 101054cdfe51SGerd Hoffmann int limit = 100; 10112b2325ffSGerd Hoffmann 10122b2325ffSGerd Hoffmann QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { 10132b2325ffSGerd Hoffmann usb_host_req_abort(r); 10142b2325ffSGerd Hoffmann } 101576d0a936SGerd Hoffmann 101676d0a936SGerd Hoffmann while (QTAILQ_FIRST(&s->requests) != NULL) { 101776d0a936SGerd Hoffmann struct timeval tv; 101876d0a936SGerd Hoffmann memset(&tv, 0, sizeof(tv)); 101976d0a936SGerd Hoffmann tv.tv_usec = 2500; 102076d0a936SGerd Hoffmann libusb_handle_events_timeout(ctx, &tv); 102154cdfe51SGerd Hoffmann if (--limit == 0) { 102254cdfe51SGerd Hoffmann /* 102354cdfe51SGerd Hoffmann * Don't wait forever for libusb calling the complete 102454cdfe51SGerd Hoffmann * callback (which will unlink and free the request). 102554cdfe51SGerd Hoffmann * 102654cdfe51SGerd Hoffmann * Leaking memory here, to make sure libusb will not 102754cdfe51SGerd Hoffmann * access memory which we have released already. 102854cdfe51SGerd Hoffmann */ 102954cdfe51SGerd Hoffmann QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { 103054cdfe51SGerd Hoffmann QTAILQ_REMOVE(&s->requests, r, next); 103154cdfe51SGerd Hoffmann } 103254cdfe51SGerd Hoffmann return; 103354cdfe51SGerd Hoffmann } 103476d0a936SGerd Hoffmann } 10352b2325ffSGerd Hoffmann } 10362b2325ffSGerd Hoffmann 10372b2325ffSGerd Hoffmann static int usb_host_close(USBHostDevice *s) 10382b2325ffSGerd Hoffmann { 10392b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 10402b2325ffSGerd Hoffmann 10412b2325ffSGerd Hoffmann if (s->dh == NULL) { 10422b2325ffSGerd Hoffmann return -1; 10432b2325ffSGerd Hoffmann } 10442b2325ffSGerd Hoffmann 10452b2325ffSGerd Hoffmann trace_usb_host_close(s->bus_num, s->addr); 10462b2325ffSGerd Hoffmann 10472b2325ffSGerd Hoffmann usb_host_abort_xfers(s); 10482b2325ffSGerd Hoffmann usb_host_iso_free_all(s); 10492b2325ffSGerd Hoffmann 10502b2325ffSGerd Hoffmann if (udev->attached) { 10512b2325ffSGerd Hoffmann usb_device_detach(udev); 10522b2325ffSGerd Hoffmann } 10532b2325ffSGerd Hoffmann 10542b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 10552b2325ffSGerd Hoffmann libusb_reset_device(s->dh); 10562b2325ffSGerd Hoffmann usb_host_attach_kernel(s); 10572b2325ffSGerd Hoffmann libusb_close(s->dh); 10582b2325ffSGerd Hoffmann s->dh = NULL; 10592b2325ffSGerd Hoffmann s->dev = NULL; 10602b2325ffSGerd Hoffmann 10619f815e83SGerd Hoffmann if (s->hostfd != -1) { 10629f815e83SGerd Hoffmann close(s->hostfd); 10639f815e83SGerd Hoffmann s->hostfd = -1; 10649f815e83SGerd Hoffmann } 10659f815e83SGerd Hoffmann 10662b2325ffSGerd Hoffmann usb_host_auto_check(NULL); 10672b2325ffSGerd Hoffmann return 0; 10682b2325ffSGerd Hoffmann } 10692b2325ffSGerd Hoffmann 10702b2325ffSGerd Hoffmann static void usb_host_nodev_bh(void *opaque) 10712b2325ffSGerd Hoffmann { 10722b2325ffSGerd Hoffmann USBHostDevice *s = opaque; 10732b2325ffSGerd Hoffmann usb_host_close(s); 10742b2325ffSGerd Hoffmann } 10752b2325ffSGerd Hoffmann 10762b2325ffSGerd Hoffmann static void usb_host_nodev(USBHostDevice *s) 10772b2325ffSGerd Hoffmann { 107895efb20cSGerd Hoffmann if (!s->bh_nodev) { 107995efb20cSGerd Hoffmann s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s); 10802b2325ffSGerd Hoffmann } 108195efb20cSGerd Hoffmann qemu_bh_schedule(s->bh_nodev); 10822b2325ffSGerd Hoffmann } 10832b2325ffSGerd Hoffmann 10842b2325ffSGerd Hoffmann static void usb_host_exit_notifier(struct Notifier *n, void *data) 10852b2325ffSGerd Hoffmann { 10862b2325ffSGerd Hoffmann USBHostDevice *s = container_of(n, USBHostDevice, exit); 10872b2325ffSGerd Hoffmann 10882b2325ffSGerd Hoffmann if (s->dh) { 108976d0a936SGerd Hoffmann usb_host_abort_xfers(s); 10902b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 10915621d045Slinzhecheng libusb_reset_device(s->dh); 10922b2325ffSGerd Hoffmann usb_host_attach_kernel(s); 10935621d045Slinzhecheng libusb_close(s->dh); 10942b2325ffSGerd Hoffmann } 10952b2325ffSGerd Hoffmann } 10962b2325ffSGerd Hoffmann 1097e058fa2dSGerd Hoffmann static libusb_device *usb_host_find_ref(int bus, int addr) 1098e058fa2dSGerd Hoffmann { 1099e058fa2dSGerd Hoffmann libusb_device **devs = NULL; 1100e058fa2dSGerd Hoffmann libusb_device *ret = NULL; 1101e058fa2dSGerd Hoffmann int i, n; 1102e058fa2dSGerd Hoffmann 1103e058fa2dSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 1104e058fa2dSGerd Hoffmann for (i = 0; i < n; i++) { 1105e058fa2dSGerd Hoffmann if (libusb_get_bus_number(devs[i]) == bus && 1106e058fa2dSGerd Hoffmann libusb_get_device_address(devs[i]) == addr) { 1107e058fa2dSGerd Hoffmann ret = libusb_ref_device(devs[i]); 1108e058fa2dSGerd Hoffmann break; 1109e058fa2dSGerd Hoffmann } 1110e058fa2dSGerd Hoffmann } 1111e058fa2dSGerd Hoffmann libusb_free_device_list(devs, 1); 1112e058fa2dSGerd Hoffmann return ret; 1113e058fa2dSGerd Hoffmann } 1114e058fa2dSGerd Hoffmann 11152aa76dc1SGonglei static void usb_host_realize(USBDevice *udev, Error **errp) 11162b2325ffSGerd Hoffmann { 11172b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 1118e058fa2dSGerd Hoffmann libusb_device *ldev; 1119e058fa2dSGerd Hoffmann int rc; 11202b2325ffSGerd Hoffmann 11219f815e83SGerd Hoffmann if (usb_host_init() != 0) { 11229f815e83SGerd Hoffmann error_setg(errp, "failed to init libusb"); 11239f815e83SGerd Hoffmann return; 11249f815e83SGerd Hoffmann } 1125f3cda6e0SGerd Hoffmann if (s->match.vendor_id > 0xffff) { 11262aa76dc1SGonglei error_setg(errp, "vendorid out of range"); 11272aa76dc1SGonglei return; 1128f3cda6e0SGerd Hoffmann } 1129f3cda6e0SGerd Hoffmann if (s->match.product_id > 0xffff) { 11302aa76dc1SGonglei error_setg(errp, "productid out of range"); 11312aa76dc1SGonglei return; 1132f3cda6e0SGerd Hoffmann } 1133f3cda6e0SGerd Hoffmann if (s->match.addr > 127) { 11342aa76dc1SGonglei error_setg(errp, "hostaddr out of range"); 11352aa76dc1SGonglei return; 1136f3cda6e0SGerd Hoffmann } 1137f3cda6e0SGerd Hoffmann 11382b2325ffSGerd Hoffmann loglevel = s->loglevel; 1139628e5485SGerd Hoffmann udev->flags |= (1 << USB_DEV_FLAG_IS_HOST); 11402b2325ffSGerd Hoffmann udev->auto_attach = 0; 11412b2325ffSGerd Hoffmann QTAILQ_INIT(&s->requests); 11422b2325ffSGerd Hoffmann QTAILQ_INIT(&s->isorings); 11439f815e83SGerd Hoffmann s->hostfd = -1; 11442b2325ffSGerd Hoffmann 1145631009e7SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) 11469f815e83SGerd Hoffmann if (s->hostdevice) { 11479f815e83SGerd Hoffmann int fd; 11489f815e83SGerd Hoffmann s->needs_autoscan = false; 1149448058aaSDaniel P. Berrangé fd = qemu_open_old(s->hostdevice, O_RDWR); 11509f815e83SGerd Hoffmann if (fd < 0) { 11519f815e83SGerd Hoffmann error_setg_errno(errp, errno, "failed to open %s", s->hostdevice); 11529f815e83SGerd Hoffmann return; 11539f815e83SGerd Hoffmann } 11549f815e83SGerd Hoffmann rc = usb_host_open(s, NULL, fd); 11559f815e83SGerd Hoffmann if (rc < 0) { 11569f815e83SGerd Hoffmann error_setg(errp, "failed to open host usb device %s", s->hostdevice); 11579f815e83SGerd Hoffmann return; 11589f815e83SGerd Hoffmann } 11599f815e83SGerd Hoffmann } else 11609f815e83SGerd Hoffmann #endif 1161e058fa2dSGerd Hoffmann if (s->match.addr && s->match.bus_num && 1162e058fa2dSGerd Hoffmann !s->match.vendor_id && 1163e058fa2dSGerd Hoffmann !s->match.product_id && 1164e058fa2dSGerd Hoffmann !s->match.port) { 1165e058fa2dSGerd Hoffmann s->needs_autoscan = false; 1166e058fa2dSGerd Hoffmann ldev = usb_host_find_ref(s->match.bus_num, 1167e058fa2dSGerd Hoffmann s->match.addr); 1168e058fa2dSGerd Hoffmann if (!ldev) { 1169e058fa2dSGerd Hoffmann error_setg(errp, "failed to find host usb device %d:%d", 1170e058fa2dSGerd Hoffmann s->match.bus_num, s->match.addr); 1171e058fa2dSGerd Hoffmann return; 1172e058fa2dSGerd Hoffmann } 11739f815e83SGerd Hoffmann rc = usb_host_open(s, ldev, 0); 1174e058fa2dSGerd Hoffmann libusb_unref_device(ldev); 1175e058fa2dSGerd Hoffmann if (rc < 0) { 1176e058fa2dSGerd Hoffmann error_setg(errp, "failed to open host usb device %d:%d", 1177e058fa2dSGerd Hoffmann s->match.bus_num, s->match.addr); 1178e058fa2dSGerd Hoffmann return; 1179e058fa2dSGerd Hoffmann } 1180e058fa2dSGerd Hoffmann } else { 1181e058fa2dSGerd Hoffmann s->needs_autoscan = true; 11822b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&hostdevs, s, next); 11832b2325ffSGerd Hoffmann usb_host_auto_check(NULL); 11842b2325ffSGerd Hoffmann } 11852b2325ffSGerd Hoffmann 1186e058fa2dSGerd Hoffmann s->exit.notify = usb_host_exit_notifier; 1187e058fa2dSGerd Hoffmann qemu_add_exit_notifier(&s->exit); 1188e058fa2dSGerd Hoffmann } 1189e058fa2dSGerd Hoffmann 1190e6adae52SGonglei static void usb_host_instance_init(Object *obj) 1191e6adae52SGonglei { 1192e6adae52SGonglei USBDevice *udev = USB_DEVICE(obj); 1193e6adae52SGonglei USBHostDevice *s = USB_HOST_DEVICE(udev); 1194e6adae52SGonglei 1195e6adae52SGonglei device_add_bootindex_property(obj, &s->bootindex, 1196e6adae52SGonglei "bootindex", NULL, 119740c2281cSMarkus Armbruster &udev->qdev); 1198e6adae52SGonglei } 1199e6adae52SGonglei 1200b69c3c21SMarkus Armbruster static void usb_host_unrealize(USBDevice *udev) 12012b2325ffSGerd Hoffmann { 12022b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 12032b2325ffSGerd Hoffmann 12042b2325ffSGerd Hoffmann qemu_remove_exit_notifier(&s->exit); 1205e058fa2dSGerd Hoffmann if (s->needs_autoscan) { 12062b2325ffSGerd Hoffmann QTAILQ_REMOVE(&hostdevs, s, next); 1207e058fa2dSGerd Hoffmann } 12082b2325ffSGerd Hoffmann usb_host_close(s); 12092b2325ffSGerd Hoffmann } 12102b2325ffSGerd Hoffmann 12112b2325ffSGerd Hoffmann static void usb_host_cancel_packet(USBDevice *udev, USBPacket *p) 12122b2325ffSGerd Hoffmann { 12132b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 12142b2325ffSGerd Hoffmann USBHostRequest *r; 12152b2325ffSGerd Hoffmann 12162b2325ffSGerd Hoffmann if (p->combined) { 12172b2325ffSGerd Hoffmann usb_combined_packet_cancel(udev, p); 12182b2325ffSGerd Hoffmann return; 12192b2325ffSGerd Hoffmann } 12202b2325ffSGerd Hoffmann 12212b2325ffSGerd Hoffmann trace_usb_host_req_canceled(s->bus_num, s->addr, p); 12222b2325ffSGerd Hoffmann 12232b2325ffSGerd Hoffmann r = usb_host_req_find(s, p); 12242b2325ffSGerd Hoffmann if (r && r->p) { 12252b2325ffSGerd Hoffmann r->p = NULL; /* mark as dead */ 12262b2325ffSGerd Hoffmann libusb_cancel_transfer(r->xfer); 12272b2325ffSGerd Hoffmann } 12282b2325ffSGerd Hoffmann } 12292b2325ffSGerd Hoffmann 12302b2325ffSGerd Hoffmann static void usb_host_detach_kernel(USBHostDevice *s) 12312b2325ffSGerd Hoffmann { 12322b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 12332b2325ffSGerd Hoffmann int rc, i; 12342b2325ffSGerd Hoffmann 12352b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 12362b2325ffSGerd Hoffmann if (rc != 0) { 12372b2325ffSGerd Hoffmann return; 12382b2325ffSGerd Hoffmann } 1239896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 12402b2325ffSGerd Hoffmann rc = libusb_kernel_driver_active(s->dh, i); 12412b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_kernel_driver_active", rc); 12422b2325ffSGerd Hoffmann if (rc != 1) { 1243933d2d4bSlinzhecheng if (rc == 0) { 1244933d2d4bSlinzhecheng s->ifs[i].detached = true; 1245933d2d4bSlinzhecheng } 12462b2325ffSGerd Hoffmann continue; 12472b2325ffSGerd Hoffmann } 12482b2325ffSGerd Hoffmann trace_usb_host_detach_kernel(s->bus_num, s->addr, i); 12492b2325ffSGerd Hoffmann rc = libusb_detach_kernel_driver(s->dh, i); 12502b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_detach_kernel_driver", rc); 12512b2325ffSGerd Hoffmann s->ifs[i].detached = true; 12522b2325ffSGerd Hoffmann } 12532b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 12542b2325ffSGerd Hoffmann } 12552b2325ffSGerd Hoffmann 12562b2325ffSGerd Hoffmann static void usb_host_attach_kernel(USBHostDevice *s) 12572b2325ffSGerd Hoffmann { 12582b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 12592b2325ffSGerd Hoffmann int rc, i; 12602b2325ffSGerd Hoffmann 12612b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 12622b2325ffSGerd Hoffmann if (rc != 0) { 12632b2325ffSGerd Hoffmann return; 12642b2325ffSGerd Hoffmann } 1265896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 12662b2325ffSGerd Hoffmann if (!s->ifs[i].detached) { 12672b2325ffSGerd Hoffmann continue; 12682b2325ffSGerd Hoffmann } 12692b2325ffSGerd Hoffmann trace_usb_host_attach_kernel(s->bus_num, s->addr, i); 12702b2325ffSGerd Hoffmann libusb_attach_kernel_driver(s->dh, i); 12712b2325ffSGerd Hoffmann s->ifs[i].detached = false; 12722b2325ffSGerd Hoffmann } 12732b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 12742b2325ffSGerd Hoffmann } 12752b2325ffSGerd Hoffmann 12762b2325ffSGerd Hoffmann static int usb_host_claim_interfaces(USBHostDevice *s, int configuration) 12772b2325ffSGerd Hoffmann { 12782b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 12792b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 1280896b6757SSamuel Brian int rc, i, claimed; 12812b2325ffSGerd Hoffmann 12822b2325ffSGerd Hoffmann for (i = 0; i < USB_MAX_INTERFACES; i++) { 12832b2325ffSGerd Hoffmann udev->altsetting[i] = 0; 12842b2325ffSGerd Hoffmann } 12852b2325ffSGerd Hoffmann udev->ninterfaces = 0; 12862b2325ffSGerd Hoffmann udev->configuration = 0; 12872b2325ffSGerd Hoffmann 12882b2325ffSGerd Hoffmann usb_host_detach_kernel(s); 12892b2325ffSGerd Hoffmann 12902b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 12912b2325ffSGerd Hoffmann if (rc != 0) { 12921294ca79SHans de Goede if (rc == LIBUSB_ERROR_NOT_FOUND) { 12931294ca79SHans de Goede /* address state - ignore */ 12941294ca79SHans de Goede return USB_RET_SUCCESS; 12951294ca79SHans de Goede } 12962b2325ffSGerd Hoffmann return USB_RET_STALL; 12972b2325ffSGerd Hoffmann } 12982b2325ffSGerd Hoffmann 1299896b6757SSamuel Brian claimed = 0; 1300896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13012b2325ffSGerd Hoffmann trace_usb_host_claim_interface(s->bus_num, s->addr, configuration, i); 13022b2325ffSGerd Hoffmann rc = libusb_claim_interface(s->dh, i); 1303896b6757SSamuel Brian if (rc == 0) { 13042b2325ffSGerd Hoffmann s->ifs[i].claimed = true; 1305896b6757SSamuel Brian if (++claimed == conf->bNumInterfaces) { 1306896b6757SSamuel Brian break; 1307896b6757SSamuel Brian } 1308896b6757SSamuel Brian } 1309896b6757SSamuel Brian } 1310896b6757SSamuel Brian if (claimed != conf->bNumInterfaces) { 1311896b6757SSamuel Brian return USB_RET_STALL; 13122b2325ffSGerd Hoffmann } 13132b2325ffSGerd Hoffmann 13142b2325ffSGerd Hoffmann udev->ninterfaces = conf->bNumInterfaces; 13152b2325ffSGerd Hoffmann udev->configuration = configuration; 13162b2325ffSGerd Hoffmann 13172b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 13182b2325ffSGerd Hoffmann return USB_RET_SUCCESS; 13192b2325ffSGerd Hoffmann } 13202b2325ffSGerd Hoffmann 13212b2325ffSGerd Hoffmann static void usb_host_release_interfaces(USBHostDevice *s) 13222b2325ffSGerd Hoffmann { 13232b2325ffSGerd Hoffmann int i, rc; 13242b2325ffSGerd Hoffmann 1325896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13262b2325ffSGerd Hoffmann if (!s->ifs[i].claimed) { 13272b2325ffSGerd Hoffmann continue; 13282b2325ffSGerd Hoffmann } 13292b2325ffSGerd Hoffmann trace_usb_host_release_interface(s->bus_num, s->addr, i); 13302b2325ffSGerd Hoffmann rc = libusb_release_interface(s->dh, i); 13312b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_release_interface", rc); 13322b2325ffSGerd Hoffmann s->ifs[i].claimed = false; 13332b2325ffSGerd Hoffmann } 13342b2325ffSGerd Hoffmann } 13352b2325ffSGerd Hoffmann 13362b2325ffSGerd Hoffmann static void usb_host_set_address(USBHostDevice *s, int addr) 13372b2325ffSGerd Hoffmann { 13382b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 13392b2325ffSGerd Hoffmann 13402b2325ffSGerd Hoffmann trace_usb_host_set_address(s->bus_num, s->addr, addr); 13412b2325ffSGerd Hoffmann udev->addr = addr; 13422b2325ffSGerd Hoffmann } 13432b2325ffSGerd Hoffmann 13442b2325ffSGerd Hoffmann static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p) 13452b2325ffSGerd Hoffmann { 1346bfe44898SGerd Hoffmann int rc = 0; 13472b2325ffSGerd Hoffmann 13482b2325ffSGerd Hoffmann trace_usb_host_set_config(s->bus_num, s->addr, config); 13492b2325ffSGerd Hoffmann 13502b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 1351bfe44898SGerd Hoffmann if (s->ddesc.bNumConfigurations != 1) { 13522b2325ffSGerd Hoffmann rc = libusb_set_configuration(s->dh, config); 13532b2325ffSGerd Hoffmann if (rc != 0) { 13542b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_set_configuration", rc); 13552b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 13562b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 13572b2325ffSGerd Hoffmann usb_host_nodev(s); 13582b2325ffSGerd Hoffmann } 13592b2325ffSGerd Hoffmann return; 13602b2325ffSGerd Hoffmann } 1361bfe44898SGerd Hoffmann } 13622b2325ffSGerd Hoffmann p->status = usb_host_claim_interfaces(s, config); 13632b2325ffSGerd Hoffmann if (p->status != USB_RET_SUCCESS) { 13642b2325ffSGerd Hoffmann return; 13652b2325ffSGerd Hoffmann } 13662b2325ffSGerd Hoffmann usb_host_ep_update(s); 13672b2325ffSGerd Hoffmann } 13682b2325ffSGerd Hoffmann 13692b2325ffSGerd Hoffmann static void usb_host_set_interface(USBHostDevice *s, int iface, int alt, 13702b2325ffSGerd Hoffmann USBPacket *p) 13712b2325ffSGerd Hoffmann { 13722b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 13732b2325ffSGerd Hoffmann int rc; 13742b2325ffSGerd Hoffmann 13752b2325ffSGerd Hoffmann trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt); 13762b2325ffSGerd Hoffmann 13772b2325ffSGerd Hoffmann usb_host_iso_free_all(s); 13782b2325ffSGerd Hoffmann 13792b2325ffSGerd Hoffmann if (iface >= USB_MAX_INTERFACES) { 13802b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 13812b2325ffSGerd Hoffmann return; 13822b2325ffSGerd Hoffmann } 13832b2325ffSGerd Hoffmann 13842b2325ffSGerd Hoffmann rc = libusb_set_interface_alt_setting(s->dh, iface, alt); 13852b2325ffSGerd Hoffmann if (rc != 0) { 13862b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_set_interface_alt_setting", rc); 13872b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 13882b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 13892b2325ffSGerd Hoffmann usb_host_nodev(s); 13902b2325ffSGerd Hoffmann } 13912b2325ffSGerd Hoffmann return; 13922b2325ffSGerd Hoffmann } 13932b2325ffSGerd Hoffmann 13942b2325ffSGerd Hoffmann udev->altsetting[iface] = alt; 13952b2325ffSGerd Hoffmann usb_host_ep_update(s); 13962b2325ffSGerd Hoffmann } 13972b2325ffSGerd Hoffmann 13982b2325ffSGerd Hoffmann static void usb_host_handle_control(USBDevice *udev, USBPacket *p, 13992b2325ffSGerd Hoffmann int request, int value, int index, 14002b2325ffSGerd Hoffmann int length, uint8_t *data) 14012b2325ffSGerd Hoffmann { 14022b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 14032b2325ffSGerd Hoffmann USBHostRequest *r; 14042b2325ffSGerd Hoffmann int rc; 14052b2325ffSGerd Hoffmann 14062b2325ffSGerd Hoffmann trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); 14072b2325ffSGerd Hoffmann 14082b2325ffSGerd Hoffmann if (s->dh == NULL) { 14092b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 14102b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14112b2325ffSGerd Hoffmann return; 14122b2325ffSGerd Hoffmann } 14132b2325ffSGerd Hoffmann 14142b2325ffSGerd Hoffmann switch (request) { 14152b2325ffSGerd Hoffmann case DeviceOutRequest | USB_REQ_SET_ADDRESS: 14162b2325ffSGerd Hoffmann usb_host_set_address(s, value); 14172b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14182b2325ffSGerd Hoffmann return; 14192b2325ffSGerd Hoffmann 14202b2325ffSGerd Hoffmann case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: 14212b2325ffSGerd Hoffmann usb_host_set_config(s, value & 0xff, p); 14222b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14232b2325ffSGerd Hoffmann return; 14242b2325ffSGerd Hoffmann 14252b2325ffSGerd Hoffmann case InterfaceOutRequest | USB_REQ_SET_INTERFACE: 14262b2325ffSGerd Hoffmann usb_host_set_interface(s, index, value, p); 14272b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14282b2325ffSGerd Hoffmann return; 14292b2325ffSGerd Hoffmann 14302b2325ffSGerd Hoffmann case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: 14312b2325ffSGerd Hoffmann if (value == 0) { /* clear halt */ 14322b2325ffSGerd Hoffmann int pid = (index & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; 14332b2325ffSGerd Hoffmann libusb_clear_halt(s->dh, index); 14342b2325ffSGerd Hoffmann usb_ep_set_halted(udev, pid, index & 0x0f, 0); 14352b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14362b2325ffSGerd Hoffmann return; 14372b2325ffSGerd Hoffmann } 14382b2325ffSGerd Hoffmann } 14392b2325ffSGerd Hoffmann 14402b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, (request >> 8) & USB_DIR_IN, length + 8); 14412b2325ffSGerd Hoffmann r->cbuf = data; 14422b2325ffSGerd Hoffmann r->clen = length; 14432b2325ffSGerd Hoffmann memcpy(r->buffer, udev->setup_buf, 8); 14442b2325ffSGerd Hoffmann if (!r->in) { 14452b2325ffSGerd Hoffmann memcpy(r->buffer + 8, r->cbuf, r->clen); 14462b2325ffSGerd Hoffmann } 14472b2325ffSGerd Hoffmann 1448b88a3e01SGerd Hoffmann /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices 1449b88a3e01SGerd Hoffmann * to work redirected to a not superspeed capable hcd */ 1450a9be4e7cSGerd Hoffmann if ((udev->speedmask & USB_SPEED_MASK_SUPER) && 145172517114Slijun !(udev->port->speedmask & USB_SPEED_MASK_SUPER) && 1452b88a3e01SGerd Hoffmann request == 0x8006 && value == 0x100 && index == 0) { 1453b88a3e01SGerd Hoffmann r->usb3ep0quirk = true; 1454b88a3e01SGerd Hoffmann } 1455b88a3e01SGerd Hoffmann 14562b2325ffSGerd Hoffmann libusb_fill_control_transfer(r->xfer, s->dh, r->buffer, 14572b2325ffSGerd Hoffmann usb_host_req_complete_ctrl, r, 14582b2325ffSGerd Hoffmann CONTROL_TIMEOUT); 14592b2325ffSGerd Hoffmann rc = libusb_submit_transfer(r->xfer); 14602b2325ffSGerd Hoffmann if (rc != 0) { 14612b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 14622b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 14632b2325ffSGerd Hoffmann p->status, p->actual_length); 14642b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 14652b2325ffSGerd Hoffmann usb_host_nodev(s); 14662b2325ffSGerd Hoffmann } 14672b2325ffSGerd Hoffmann return; 14682b2325ffSGerd Hoffmann } 14692b2325ffSGerd Hoffmann 14702b2325ffSGerd Hoffmann p->status = USB_RET_ASYNC; 14712b2325ffSGerd Hoffmann } 14722b2325ffSGerd Hoffmann 14732b2325ffSGerd Hoffmann static void usb_host_handle_data(USBDevice *udev, USBPacket *p) 14742b2325ffSGerd Hoffmann { 14752b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 14762b2325ffSGerd Hoffmann USBHostRequest *r; 14772b2325ffSGerd Hoffmann size_t size; 14782b2325ffSGerd Hoffmann int ep, rc; 14792b2325ffSGerd Hoffmann 14802b2325ffSGerd Hoffmann if (usb_host_use_combining(p->ep) && p->state == USB_PACKET_SETUP) { 14812b2325ffSGerd Hoffmann p->status = USB_RET_ADD_TO_QUEUE; 14822b2325ffSGerd Hoffmann return; 14832b2325ffSGerd Hoffmann } 14842b2325ffSGerd Hoffmann 14852b2325ffSGerd Hoffmann trace_usb_host_req_data(s->bus_num, s->addr, p, 14862b2325ffSGerd Hoffmann p->pid == USB_TOKEN_IN, 14872b2325ffSGerd Hoffmann p->ep->nr, p->iov.size); 14882b2325ffSGerd Hoffmann 14892b2325ffSGerd Hoffmann if (s->dh == NULL) { 14902b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 14912b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14922b2325ffSGerd Hoffmann return; 14932b2325ffSGerd Hoffmann } 14942b2325ffSGerd Hoffmann if (p->ep->halted) { 14952b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 14962b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14972b2325ffSGerd Hoffmann return; 14982b2325ffSGerd Hoffmann } 14992b2325ffSGerd Hoffmann 15002b2325ffSGerd Hoffmann switch (usb_ep_get_type(udev, p->pid, p->ep->nr)) { 15012b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_BULK: 15022b2325ffSGerd Hoffmann size = usb_packet_size(p); 15032b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, p->pid == USB_TOKEN_IN, size); 15042b2325ffSGerd Hoffmann if (!r->in) { 15052b2325ffSGerd Hoffmann usb_packet_copy(p, r->buffer, size); 15062b2325ffSGerd Hoffmann } 15072b2325ffSGerd Hoffmann ep = p->ep->nr | (r->in ? USB_DIR_IN : 0); 15088d1bd3c9SHans de Goede if (p->stream) { 1509322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 15108d1bd3c9SHans de Goede libusb_fill_bulk_stream_transfer(r->xfer, s->dh, ep, p->stream, 15118d1bd3c9SHans de Goede r->buffer, size, 15128d1bd3c9SHans de Goede usb_host_req_complete_data, r, 15138d1bd3c9SHans de Goede BULK_TIMEOUT); 15148d1bd3c9SHans de Goede #else 15158d1bd3c9SHans de Goede usb_host_req_free(r); 15168d1bd3c9SHans de Goede p->status = USB_RET_STALL; 15178d1bd3c9SHans de Goede return; 15188d1bd3c9SHans de Goede #endif 15198d1bd3c9SHans de Goede } else { 15202b2325ffSGerd Hoffmann libusb_fill_bulk_transfer(r->xfer, s->dh, ep, 15212b2325ffSGerd Hoffmann r->buffer, size, 15222b2325ffSGerd Hoffmann usb_host_req_complete_data, r, 15232b2325ffSGerd Hoffmann BULK_TIMEOUT); 15248d1bd3c9SHans de Goede } 15252b2325ffSGerd Hoffmann break; 15262b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_INT: 15272b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, p->pid == USB_TOKEN_IN, p->iov.size); 15282b2325ffSGerd Hoffmann if (!r->in) { 15292b2325ffSGerd Hoffmann usb_packet_copy(p, r->buffer, p->iov.size); 15302b2325ffSGerd Hoffmann } 15312b2325ffSGerd Hoffmann ep = p->ep->nr | (r->in ? USB_DIR_IN : 0); 15322b2325ffSGerd Hoffmann libusb_fill_interrupt_transfer(r->xfer, s->dh, ep, 15332b2325ffSGerd Hoffmann r->buffer, p->iov.size, 15342b2325ffSGerd Hoffmann usb_host_req_complete_data, r, 15352b2325ffSGerd Hoffmann INTR_TIMEOUT); 15362b2325ffSGerd Hoffmann break; 15372b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_ISOC: 15382b2325ffSGerd Hoffmann if (p->pid == USB_TOKEN_IN) { 15392b2325ffSGerd Hoffmann usb_host_iso_data_in(s, p); 15402b2325ffSGerd Hoffmann } else { 15412b2325ffSGerd Hoffmann usb_host_iso_data_out(s, p); 15422b2325ffSGerd Hoffmann } 15432b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 15442b2325ffSGerd Hoffmann p->status, p->actual_length); 15452b2325ffSGerd Hoffmann return; 15462b2325ffSGerd Hoffmann default: 15472b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 15482b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 15492b2325ffSGerd Hoffmann p->status, p->actual_length); 15502b2325ffSGerd Hoffmann return; 15512b2325ffSGerd Hoffmann } 15522b2325ffSGerd Hoffmann 15532b2325ffSGerd Hoffmann rc = libusb_submit_transfer(r->xfer); 15542b2325ffSGerd Hoffmann if (rc != 0) { 15552b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 15562b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 15572b2325ffSGerd Hoffmann p->status, p->actual_length); 15582b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 15592b2325ffSGerd Hoffmann usb_host_nodev(s); 15602b2325ffSGerd Hoffmann } 15612b2325ffSGerd Hoffmann return; 15622b2325ffSGerd Hoffmann } 15632b2325ffSGerd Hoffmann 15642b2325ffSGerd Hoffmann p->status = USB_RET_ASYNC; 15652b2325ffSGerd Hoffmann } 15662b2325ffSGerd Hoffmann 15672b2325ffSGerd Hoffmann static void usb_host_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) 15682b2325ffSGerd Hoffmann { 15692b2325ffSGerd Hoffmann if (usb_host_use_combining(ep)) { 15702b2325ffSGerd Hoffmann usb_ep_combine_input_packets(ep); 15712b2325ffSGerd Hoffmann } 15722b2325ffSGerd Hoffmann } 15732b2325ffSGerd Hoffmann 15742b2325ffSGerd Hoffmann static void usb_host_handle_reset(USBDevice *udev) 15752b2325ffSGerd Hoffmann { 15762b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 15775af35d7fSHans de Goede int rc; 15782b2325ffSGerd Hoffmann 15791dfe2b91SGerd Hoffmann if (!s->allow_one_guest_reset && !s->allow_all_guest_resets) { 1580ba4c735bSAlexander Kappner return; 1581ba4c735bSAlexander Kappner } 15821dfe2b91SGerd Hoffmann if (!s->allow_all_guest_resets && udev->addr == 0) { 158365f14ab9SGerd Hoffmann return; 158465f14ab9SGerd Hoffmann } 1585ba4c735bSAlexander Kappner 15862b2325ffSGerd Hoffmann trace_usb_host_reset(s->bus_num, s->addr); 15872b2325ffSGerd Hoffmann 15885af35d7fSHans de Goede rc = libusb_reset_device(s->dh); 15895af35d7fSHans de Goede if (rc != 0) { 15905af35d7fSHans de Goede usb_host_nodev(s); 15912b2325ffSGerd Hoffmann } 15922b2325ffSGerd Hoffmann } 15932b2325ffSGerd Hoffmann 159456a9f180SHans de Goede static int usb_host_alloc_streams(USBDevice *udev, USBEndpoint **eps, 159556a9f180SHans de Goede int nr_eps, int streams) 159656a9f180SHans de Goede { 1597322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 159856a9f180SHans de Goede USBHostDevice *s = USB_HOST_DEVICE(udev); 159956a9f180SHans de Goede unsigned char endpoints[30]; 160056a9f180SHans de Goede int i, rc; 160156a9f180SHans de Goede 160256a9f180SHans de Goede for (i = 0; i < nr_eps; i++) { 160356a9f180SHans de Goede endpoints[i] = eps[i]->nr; 160456a9f180SHans de Goede if (eps[i]->pid == USB_TOKEN_IN) { 160556a9f180SHans de Goede endpoints[i] |= 0x80; 160656a9f180SHans de Goede } 160756a9f180SHans de Goede } 160856a9f180SHans de Goede rc = libusb_alloc_streams(s->dh, streams, endpoints, nr_eps); 160956a9f180SHans de Goede if (rc < 0) { 161056a9f180SHans de Goede usb_host_libusb_error("libusb_alloc_streams", rc); 161156a9f180SHans de Goede } else if (rc != streams) { 16122e6a0dd1SGonglei error_report("libusb_alloc_streams: got less streams " 16132e6a0dd1SGonglei "then requested %d < %d", rc, streams); 161456a9f180SHans de Goede } 161556a9f180SHans de Goede 161656a9f180SHans de Goede return (rc == streams) ? 0 : -1; 161756a9f180SHans de Goede #else 16182e6a0dd1SGonglei error_report("libusb_alloc_streams: error not implemented"); 161956a9f180SHans de Goede return -1; 162056a9f180SHans de Goede #endif 162156a9f180SHans de Goede } 162256a9f180SHans de Goede 162356a9f180SHans de Goede static void usb_host_free_streams(USBDevice *udev, USBEndpoint **eps, 162456a9f180SHans de Goede int nr_eps) 162556a9f180SHans de Goede { 1626322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 162756a9f180SHans de Goede USBHostDevice *s = USB_HOST_DEVICE(udev); 162856a9f180SHans de Goede unsigned char endpoints[30]; 162956a9f180SHans de Goede int i; 163056a9f180SHans de Goede 163156a9f180SHans de Goede for (i = 0; i < nr_eps; i++) { 163256a9f180SHans de Goede endpoints[i] = eps[i]->nr; 163356a9f180SHans de Goede if (eps[i]->pid == USB_TOKEN_IN) { 163456a9f180SHans de Goede endpoints[i] |= 0x80; 163556a9f180SHans de Goede } 163656a9f180SHans de Goede } 163756a9f180SHans de Goede libusb_free_streams(s->dh, endpoints, nr_eps); 163856a9f180SHans de Goede #endif 163956a9f180SHans de Goede } 164056a9f180SHans de Goede 164195efb20cSGerd Hoffmann /* 164295efb20cSGerd Hoffmann * This is *NOT* about restoring state. We have absolutely no idea 164395efb20cSGerd Hoffmann * what state the host device is in at the moment and whenever it is 164495efb20cSGerd Hoffmann * still present in the first place. Attemping to contine where we 164595efb20cSGerd Hoffmann * left off is impossible. 164695efb20cSGerd Hoffmann * 1647b6af0975SDaniel P. Berrange * What we are going to do here is emulate a surprise removal of 164895efb20cSGerd Hoffmann * the usb device passed through, then kick host scan so the device 164995efb20cSGerd Hoffmann * will get re-attached (and re-initialized by the guest) in case it 165095efb20cSGerd Hoffmann * is still present. 165195efb20cSGerd Hoffmann * 165295efb20cSGerd Hoffmann * As the device removal will change the state of other devices (usb 165395efb20cSGerd Hoffmann * host controller, most likely interrupt controller too) we have to 165495efb20cSGerd Hoffmann * wait with it until *all* vmstate is loaded. Thus post_load just 165595efb20cSGerd Hoffmann * kicks a bottom half which then does the actual work. 165695efb20cSGerd Hoffmann */ 165795efb20cSGerd Hoffmann static void usb_host_post_load_bh(void *opaque) 165895efb20cSGerd Hoffmann { 165995efb20cSGerd Hoffmann USBHostDevice *dev = opaque; 166095efb20cSGerd Hoffmann USBDevice *udev = USB_DEVICE(dev); 166195efb20cSGerd Hoffmann 166295efb20cSGerd Hoffmann if (dev->dh != NULL) { 166395efb20cSGerd Hoffmann usb_host_close(dev); 166495efb20cSGerd Hoffmann } 166595efb20cSGerd Hoffmann if (udev->attached) { 166695efb20cSGerd Hoffmann usb_device_detach(udev); 166795efb20cSGerd Hoffmann } 16683280ea8eSGerd Hoffmann dev->bh_postld_pending = false; 166995efb20cSGerd Hoffmann usb_host_auto_check(NULL); 167095efb20cSGerd Hoffmann } 167195efb20cSGerd Hoffmann 167295efb20cSGerd Hoffmann static int usb_host_post_load(void *opaque, int version_id) 167395efb20cSGerd Hoffmann { 167495efb20cSGerd Hoffmann USBHostDevice *dev = opaque; 167595efb20cSGerd Hoffmann 167695efb20cSGerd Hoffmann if (!dev->bh_postld) { 167795efb20cSGerd Hoffmann dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev); 167895efb20cSGerd Hoffmann } 167995efb20cSGerd Hoffmann qemu_bh_schedule(dev->bh_postld); 16803280ea8eSGerd Hoffmann dev->bh_postld_pending = true; 168195efb20cSGerd Hoffmann return 0; 168295efb20cSGerd Hoffmann } 168395efb20cSGerd Hoffmann 16842b2325ffSGerd Hoffmann static const VMStateDescription vmstate_usb_host = { 16852b2325ffSGerd Hoffmann .name = "usb-host", 168695efb20cSGerd Hoffmann .version_id = 1, 168795efb20cSGerd Hoffmann .minimum_version_id = 1, 168895efb20cSGerd Hoffmann .post_load = usb_host_post_load, 16892b2325ffSGerd Hoffmann .fields = (VMStateField[]) { 16902b2325ffSGerd Hoffmann VMSTATE_USB_DEVICE(parent_obj, USBHostDevice), 16912b2325ffSGerd Hoffmann VMSTATE_END_OF_LIST() 16922b2325ffSGerd Hoffmann } 16932b2325ffSGerd Hoffmann }; 16942b2325ffSGerd Hoffmann 16952b2325ffSGerd Hoffmann static Property usb_host_dev_properties[] = { 16962b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), 16972b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), 16982b2325ffSGerd Hoffmann DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), 1699c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("vendorid", USBHostDevice, match.vendor_id, 0), 1700c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), 17019f815e83SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 17029f815e83SGerd Hoffmann DEFINE_PROP_STRING("hostdevice", USBHostDevice, hostdevice), 17039f815e83SGerd Hoffmann #endif 17042b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), 17052b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), 17061dfe2b91SGerd Hoffmann DEFINE_PROP_BOOL("guest-reset", USBHostDevice, 17071dfe2b91SGerd Hoffmann allow_one_guest_reset, true), 17081dfe2b91SGerd Hoffmann DEFINE_PROP_BOOL("guest-resets-all", USBHostDevice, 17091dfe2b91SGerd Hoffmann allow_all_guest_resets, false), 17102b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel, 17112b2325ffSGerd Hoffmann LIBUSB_LOG_LEVEL_WARNING), 17122b2325ffSGerd Hoffmann DEFINE_PROP_BIT("pipeline", USBHostDevice, options, 17132b2325ffSGerd Hoffmann USB_HOST_OPT_PIPELINE, true), 17147bacaf5fSYuri Benditovich DEFINE_PROP_BOOL("suppress-remote-wake", USBHostDevice, 17157bacaf5fSYuri Benditovich suppress_remote_wake, true), 17162b2325ffSGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 17172b2325ffSGerd Hoffmann }; 17182b2325ffSGerd Hoffmann 17192b2325ffSGerd Hoffmann static void usb_host_class_initfn(ObjectClass *klass, void *data) 17202b2325ffSGerd Hoffmann { 17212b2325ffSGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 17222b2325ffSGerd Hoffmann USBDeviceClass *uc = USB_DEVICE_CLASS(klass); 17232b2325ffSGerd Hoffmann 17242aa76dc1SGonglei uc->realize = usb_host_realize; 17252b2325ffSGerd Hoffmann uc->product_desc = "USB Host Device"; 17262b2325ffSGerd Hoffmann uc->cancel_packet = usb_host_cancel_packet; 17272b2325ffSGerd Hoffmann uc->handle_data = usb_host_handle_data; 17282b2325ffSGerd Hoffmann uc->handle_control = usb_host_handle_control; 17292b2325ffSGerd Hoffmann uc->handle_reset = usb_host_handle_reset; 1730c4fe9700SMarc-André Lureau uc->unrealize = usb_host_unrealize; 17312b2325ffSGerd Hoffmann uc->flush_ep_queue = usb_host_flush_ep_queue; 173256a9f180SHans de Goede uc->alloc_streams = usb_host_alloc_streams; 173356a9f180SHans de Goede uc->free_streams = usb_host_free_streams; 17342b2325ffSGerd Hoffmann dc->vmsd = &vmstate_usb_host; 17354f67d30bSMarc-André Lureau device_class_set_props(dc, usb_host_dev_properties); 1736125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 17372b2325ffSGerd Hoffmann } 17382b2325ffSGerd Hoffmann 17392b2325ffSGerd Hoffmann static TypeInfo usb_host_dev_info = { 17402b2325ffSGerd Hoffmann .name = TYPE_USB_HOST_DEVICE, 17412b2325ffSGerd Hoffmann .parent = TYPE_USB_DEVICE, 17422b2325ffSGerd Hoffmann .instance_size = sizeof(USBHostDevice), 17432b2325ffSGerd Hoffmann .class_init = usb_host_class_initfn, 1744e6adae52SGonglei .instance_init = usb_host_instance_init, 17452b2325ffSGerd Hoffmann }; 17462b2325ffSGerd Hoffmann 17472b2325ffSGerd Hoffmann static void usb_host_register_types(void) 17482b2325ffSGerd Hoffmann { 17492b2325ffSGerd Hoffmann type_register_static(&usb_host_dev_info); 17502b2325ffSGerd Hoffmann } 17512b2325ffSGerd Hoffmann 17522b2325ffSGerd Hoffmann type_init(usb_host_register_types) 17532b2325ffSGerd Hoffmann 17542b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 17552b2325ffSGerd Hoffmann 17562b2325ffSGerd Hoffmann static QEMUTimer *usb_auto_timer; 17572b2325ffSGerd Hoffmann static VMChangeStateEntry *usb_vmstate; 17582b2325ffSGerd Hoffmann 17592b2325ffSGerd Hoffmann static void usb_host_vm_state(void *unused, int running, RunState state) 17602b2325ffSGerd Hoffmann { 17612b2325ffSGerd Hoffmann if (running) { 17622b2325ffSGerd Hoffmann usb_host_auto_check(unused); 17632b2325ffSGerd Hoffmann } 17642b2325ffSGerd Hoffmann } 17652b2325ffSGerd Hoffmann 17662b2325ffSGerd Hoffmann static void usb_host_auto_check(void *unused) 17672b2325ffSGerd Hoffmann { 17682b2325ffSGerd Hoffmann struct USBHostDevice *s; 17692b2325ffSGerd Hoffmann struct USBAutoFilter *f; 17703ce21445SJincheng Miao libusb_device **devs = NULL; 17712b2325ffSGerd Hoffmann struct libusb_device_descriptor ddesc; 17722b2325ffSGerd Hoffmann int unconnected = 0; 17732b2325ffSGerd Hoffmann int i, n; 17742b2325ffSGerd Hoffmann 17752b2325ffSGerd Hoffmann if (usb_host_init() != 0) { 17762b2325ffSGerd Hoffmann return; 17772b2325ffSGerd Hoffmann } 17782b2325ffSGerd Hoffmann 17792b2325ffSGerd Hoffmann if (runstate_is_running()) { 17802b2325ffSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 17812b2325ffSGerd Hoffmann for (i = 0; i < n; i++) { 17822b2325ffSGerd Hoffmann if (libusb_get_device_descriptor(devs[i], &ddesc) != 0) { 17832b2325ffSGerd Hoffmann continue; 17842b2325ffSGerd Hoffmann } 17852b2325ffSGerd Hoffmann if (ddesc.bDeviceClass == LIBUSB_CLASS_HUB) { 17862b2325ffSGerd Hoffmann continue; 17872b2325ffSGerd Hoffmann } 17882b2325ffSGerd Hoffmann QTAILQ_FOREACH(s, &hostdevs, next) { 17892b2325ffSGerd Hoffmann f = &s->match; 17902b2325ffSGerd Hoffmann if (f->bus_num > 0 && 17912b2325ffSGerd Hoffmann f->bus_num != libusb_get_bus_number(devs[i])) { 17922b2325ffSGerd Hoffmann continue; 17932b2325ffSGerd Hoffmann } 17942b2325ffSGerd Hoffmann if (f->addr > 0 && 17952b2325ffSGerd Hoffmann f->addr != libusb_get_device_address(devs[i])) { 17962b2325ffSGerd Hoffmann continue; 17972b2325ffSGerd Hoffmann } 17982b2325ffSGerd Hoffmann if (f->port != NULL) { 17992b2325ffSGerd Hoffmann char port[16] = "-"; 18002b2325ffSGerd Hoffmann usb_host_get_port(devs[i], port, sizeof(port)); 18012b2325ffSGerd Hoffmann if (strcmp(f->port, port) != 0) { 18022b2325ffSGerd Hoffmann continue; 18032b2325ffSGerd Hoffmann } 18042b2325ffSGerd Hoffmann } 18052b2325ffSGerd Hoffmann if (f->vendor_id > 0 && 18062b2325ffSGerd Hoffmann f->vendor_id != ddesc.idVendor) { 18072b2325ffSGerd Hoffmann continue; 18082b2325ffSGerd Hoffmann } 18092b2325ffSGerd Hoffmann if (f->product_id > 0 && 18102b2325ffSGerd Hoffmann f->product_id != ddesc.idProduct) { 18112b2325ffSGerd Hoffmann continue; 18122b2325ffSGerd Hoffmann } 18132b2325ffSGerd Hoffmann 18142b2325ffSGerd Hoffmann /* We got a match */ 18152b2325ffSGerd Hoffmann s->seen++; 18162b2325ffSGerd Hoffmann if (s->errcount >= 3) { 18172b2325ffSGerd Hoffmann continue; 18182b2325ffSGerd Hoffmann } 18192b2325ffSGerd Hoffmann if (s->dh != NULL) { 18202b2325ffSGerd Hoffmann continue; 18212b2325ffSGerd Hoffmann } 18229f815e83SGerd Hoffmann if (usb_host_open(s, devs[i], 0) < 0) { 18232b2325ffSGerd Hoffmann s->errcount++; 18242b2325ffSGerd Hoffmann continue; 18252b2325ffSGerd Hoffmann } 18262b2325ffSGerd Hoffmann break; 18272b2325ffSGerd Hoffmann } 18282b2325ffSGerd Hoffmann } 18292b2325ffSGerd Hoffmann libusb_free_device_list(devs, 1); 18302b2325ffSGerd Hoffmann 18312b2325ffSGerd Hoffmann QTAILQ_FOREACH(s, &hostdevs, next) { 18322b2325ffSGerd Hoffmann if (s->dh == NULL) { 18332b2325ffSGerd Hoffmann unconnected++; 18342b2325ffSGerd Hoffmann } 18352b2325ffSGerd Hoffmann if (s->seen == 0) { 18362b2325ffSGerd Hoffmann if (s->dh) { 18372b2325ffSGerd Hoffmann usb_host_close(s); 18382b2325ffSGerd Hoffmann } 18392b2325ffSGerd Hoffmann s->errcount = 0; 18402b2325ffSGerd Hoffmann } 18412b2325ffSGerd Hoffmann s->seen = 0; 18422b2325ffSGerd Hoffmann } 18432b2325ffSGerd Hoffmann 18442b2325ffSGerd Hoffmann #if 0 18452b2325ffSGerd Hoffmann if (unconnected == 0) { 18462b2325ffSGerd Hoffmann /* nothing to watch */ 18472b2325ffSGerd Hoffmann if (usb_auto_timer) { 1848bc72ad67SAlex Bligh timer_del(usb_auto_timer); 18492b2325ffSGerd Hoffmann trace_usb_host_auto_scan_disabled(); 18502b2325ffSGerd Hoffmann } 18512b2325ffSGerd Hoffmann return; 18522b2325ffSGerd Hoffmann } 18532b2325ffSGerd Hoffmann #endif 18542b2325ffSGerd Hoffmann } 18552b2325ffSGerd Hoffmann 18562b2325ffSGerd Hoffmann if (!usb_vmstate) { 18572b2325ffSGerd Hoffmann usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL); 18582b2325ffSGerd Hoffmann } 18592b2325ffSGerd Hoffmann if (!usb_auto_timer) { 1860bc72ad67SAlex Bligh usb_auto_timer = timer_new_ms(QEMU_CLOCK_REALTIME, usb_host_auto_check, NULL); 18612b2325ffSGerd Hoffmann if (!usb_auto_timer) { 18622b2325ffSGerd Hoffmann return; 18632b2325ffSGerd Hoffmann } 18642b2325ffSGerd Hoffmann trace_usb_host_auto_scan_enabled(); 18652b2325ffSGerd Hoffmann } 1866bc72ad67SAlex Bligh timer_mod(usb_auto_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000); 18672b2325ffSGerd Hoffmann } 18682b2325ffSGerd Hoffmann 1869b99260ebSThomas Huth /** 1870b99260ebSThomas Huth * Check whether USB host device has a USB mass storage SCSI interface 1871b99260ebSThomas Huth */ 1872b99260ebSThomas Huth bool usb_host_dev_is_scsi_storage(USBDevice *ud) 1873b99260ebSThomas Huth { 1874b99260ebSThomas Huth USBHostDevice *uhd = USB_HOST_DEVICE(ud); 1875b99260ebSThomas Huth struct libusb_config_descriptor *conf; 1876b99260ebSThomas Huth const struct libusb_interface_descriptor *intf; 1877b99260ebSThomas Huth bool is_scsi_storage = false; 1878b99260ebSThomas Huth int i; 1879b99260ebSThomas Huth 1880b99260ebSThomas Huth if (!uhd || libusb_get_active_config_descriptor(uhd->dev, &conf) != 0) { 1881b99260ebSThomas Huth return false; 1882b99260ebSThomas Huth } 1883b99260ebSThomas Huth 1884b99260ebSThomas Huth for (i = 0; i < conf->bNumInterfaces; i++) { 1885b99260ebSThomas Huth intf = &conf->interface[i].altsetting[ud->altsetting[i]]; 1886b99260ebSThomas Huth if (intf->bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE && 1887b99260ebSThomas Huth intf->bInterfaceSubClass == 6) { /* 6 means SCSI */ 1888b99260ebSThomas Huth is_scsi_storage = true; 1889b99260ebSThomas Huth break; 1890b99260ebSThomas Huth } 1891b99260ebSThomas Huth } 1892b99260ebSThomas Huth 1893b99260ebSThomas Huth libusb_free_config_descriptor(conf); 1894b99260ebSThomas Huth 1895b99260ebSThomas Huth return is_scsi_storage; 1896b99260ebSThomas Huth } 1897b99260ebSThomas Huth 18981ce6be24SMarkus Armbruster void hmp_info_usbhost(Monitor *mon, const QDict *qdict) 18992b2325ffSGerd Hoffmann { 19003ce21445SJincheng Miao libusb_device **devs = NULL; 19012b2325ffSGerd Hoffmann struct libusb_device_descriptor ddesc; 19022b2325ffSGerd Hoffmann char port[16]; 19032b2325ffSGerd Hoffmann int i, n; 19042b2325ffSGerd Hoffmann 19052b2325ffSGerd Hoffmann if (usb_host_init() != 0) { 19062b2325ffSGerd Hoffmann return; 19072b2325ffSGerd Hoffmann } 19082b2325ffSGerd Hoffmann 19092b2325ffSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 19102b2325ffSGerd Hoffmann for (i = 0; i < n; i++) { 19112b2325ffSGerd Hoffmann if (libusb_get_device_descriptor(devs[i], &ddesc) != 0) { 19122b2325ffSGerd Hoffmann continue; 19132b2325ffSGerd Hoffmann } 19142b2325ffSGerd Hoffmann if (ddesc.bDeviceClass == LIBUSB_CLASS_HUB) { 19152b2325ffSGerd Hoffmann continue; 19162b2325ffSGerd Hoffmann } 19172b2325ffSGerd Hoffmann usb_host_get_port(devs[i], port, sizeof(port)); 19182b2325ffSGerd Hoffmann monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n", 19192b2325ffSGerd Hoffmann libusb_get_bus_number(devs[i]), 19202b2325ffSGerd Hoffmann libusb_get_device_address(devs[i]), 19212b2325ffSGerd Hoffmann port, 19222b2325ffSGerd Hoffmann speed_name[libusb_get_device_speed(devs[i])]); 19232b2325ffSGerd Hoffmann monitor_printf(mon, " Class %02x:", ddesc.bDeviceClass); 19242b2325ffSGerd Hoffmann monitor_printf(mon, " USB device %04x:%04x", 19252b2325ffSGerd Hoffmann ddesc.idVendor, ddesc.idProduct); 19262b2325ffSGerd Hoffmann if (ddesc.iProduct) { 19272b2325ffSGerd Hoffmann libusb_device_handle *handle; 19282b2325ffSGerd Hoffmann if (libusb_open(devs[i], &handle) == 0) { 19292b2325ffSGerd Hoffmann unsigned char name[64] = ""; 19302b2325ffSGerd Hoffmann libusb_get_string_descriptor_ascii(handle, 19312b2325ffSGerd Hoffmann ddesc.iProduct, 19322b2325ffSGerd Hoffmann name, sizeof(name)); 19332b2325ffSGerd Hoffmann libusb_close(handle); 19342b2325ffSGerd Hoffmann monitor_printf(mon, ", %s", name); 19352b2325ffSGerd Hoffmann } 19362b2325ffSGerd Hoffmann } 19372b2325ffSGerd Hoffmann monitor_printf(mon, "\n"); 19382b2325ffSGerd Hoffmann } 19392b2325ffSGerd Hoffmann libusb_free_device_list(devs, 1); 19402b2325ffSGerd Hoffmann } 1941