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 1822980a316SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000106 1832980a316SGerd Hoffmann # define HAVE_SUPER_PLUS 1 1842980a316SGerd Hoffmann #endif 185322fd1f4SGerd Hoffmann 1862b2325ffSGerd Hoffmann static const char *speed_name[] = { 1872b2325ffSGerd Hoffmann [LIBUSB_SPEED_UNKNOWN] = "?", 1882b2325ffSGerd Hoffmann [LIBUSB_SPEED_LOW] = "1.5", 1892b2325ffSGerd Hoffmann [LIBUSB_SPEED_FULL] = "12", 1902b2325ffSGerd Hoffmann [LIBUSB_SPEED_HIGH] = "480", 1912b2325ffSGerd Hoffmann [LIBUSB_SPEED_SUPER] = "5000", 1922980a316SGerd Hoffmann #ifdef HAVE_SUPER_PLUS 1932980a316SGerd Hoffmann [LIBUSB_SPEED_SUPER_PLUS] = "5000+", 1942980a316SGerd Hoffmann #endif 1952b2325ffSGerd Hoffmann }; 1962b2325ffSGerd Hoffmann 1972b2325ffSGerd Hoffmann static const unsigned int speed_map[] = { 1982b2325ffSGerd Hoffmann [LIBUSB_SPEED_LOW] = USB_SPEED_LOW, 1992b2325ffSGerd Hoffmann [LIBUSB_SPEED_FULL] = USB_SPEED_FULL, 2002b2325ffSGerd Hoffmann [LIBUSB_SPEED_HIGH] = USB_SPEED_HIGH, 2012b2325ffSGerd Hoffmann [LIBUSB_SPEED_SUPER] = USB_SPEED_SUPER, 2022980a316SGerd Hoffmann #ifdef HAVE_SUPER_PLUS 2032980a316SGerd Hoffmann [LIBUSB_SPEED_SUPER_PLUS] = USB_SPEED_SUPER, 2042980a316SGerd Hoffmann #endif 2052b2325ffSGerd Hoffmann }; 2062b2325ffSGerd Hoffmann 2072b2325ffSGerd Hoffmann static const unsigned int status_map[] = { 2082b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_COMPLETED] = USB_RET_SUCCESS, 2092b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_ERROR] = USB_RET_IOERROR, 2102b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_TIMED_OUT] = USB_RET_IOERROR, 2112b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_CANCELLED] = USB_RET_IOERROR, 2122b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_STALL] = USB_RET_STALL, 2132b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_NO_DEVICE] = USB_RET_NODEV, 2142b2325ffSGerd Hoffmann [LIBUSB_TRANSFER_OVERFLOW] = USB_RET_BABBLE, 2152b2325ffSGerd Hoffmann }; 2162b2325ffSGerd Hoffmann 2172b2325ffSGerd Hoffmann static const char *err_names[] = { 2182b2325ffSGerd Hoffmann [-LIBUSB_ERROR_IO] = "IO", 2192b2325ffSGerd Hoffmann [-LIBUSB_ERROR_INVALID_PARAM] = "INVALID_PARAM", 2202b2325ffSGerd Hoffmann [-LIBUSB_ERROR_ACCESS] = "ACCESS", 2212b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NO_DEVICE] = "NO_DEVICE", 2222b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NOT_FOUND] = "NOT_FOUND", 2232b2325ffSGerd Hoffmann [-LIBUSB_ERROR_BUSY] = "BUSY", 2242b2325ffSGerd Hoffmann [-LIBUSB_ERROR_TIMEOUT] = "TIMEOUT", 2252b2325ffSGerd Hoffmann [-LIBUSB_ERROR_OVERFLOW] = "OVERFLOW", 2262b2325ffSGerd Hoffmann [-LIBUSB_ERROR_PIPE] = "PIPE", 2272b2325ffSGerd Hoffmann [-LIBUSB_ERROR_INTERRUPTED] = "INTERRUPTED", 2282b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NO_MEM] = "NO_MEM", 2292b2325ffSGerd Hoffmann [-LIBUSB_ERROR_NOT_SUPPORTED] = "NOT_SUPPORTED", 2302b2325ffSGerd Hoffmann [-LIBUSB_ERROR_OTHER] = "OTHER", 2312b2325ffSGerd Hoffmann }; 2322b2325ffSGerd Hoffmann 2332b2325ffSGerd Hoffmann static libusb_context *ctx; 2342b2325ffSGerd Hoffmann static uint32_t loglevel; 2352b2325ffSGerd Hoffmann 236a277c3e0SStefan Weil #ifndef CONFIG_WIN32 237a277c3e0SStefan Weil 2382b2325ffSGerd Hoffmann static void usb_host_handle_fd(void *opaque) 2392b2325ffSGerd Hoffmann { 2402b2325ffSGerd Hoffmann struct timeval tv = { 0, 0 }; 2412b2325ffSGerd Hoffmann libusb_handle_events_timeout(ctx, &tv); 2422b2325ffSGerd Hoffmann } 2432b2325ffSGerd Hoffmann 2442b2325ffSGerd Hoffmann static void usb_host_add_fd(int fd, short events, void *user_data) 2452b2325ffSGerd Hoffmann { 2462b2325ffSGerd Hoffmann qemu_set_fd_handler(fd, 2472b2325ffSGerd Hoffmann (events & POLLIN) ? usb_host_handle_fd : NULL, 2482b2325ffSGerd Hoffmann (events & POLLOUT) ? usb_host_handle_fd : NULL, 2492b2325ffSGerd Hoffmann ctx); 2502b2325ffSGerd Hoffmann } 2512b2325ffSGerd Hoffmann 2522b2325ffSGerd Hoffmann static void usb_host_del_fd(int fd, void *user_data) 2532b2325ffSGerd Hoffmann { 2542b2325ffSGerd Hoffmann qemu_set_fd_handler(fd, NULL, NULL, NULL); 2552b2325ffSGerd Hoffmann } 2562b2325ffSGerd Hoffmann 257663fdc81SGerd Hoffmann #else 258663fdc81SGerd Hoffmann 259663fdc81SGerd Hoffmann static QEMUTimer *poll_timer; 260663fdc81SGerd Hoffmann static uint32_t request_count; 261663fdc81SGerd Hoffmann 262663fdc81SGerd Hoffmann static void usb_host_timer_kick(void) 263663fdc81SGerd Hoffmann { 264663fdc81SGerd Hoffmann int64_t delay_ns; 265663fdc81SGerd Hoffmann 266663fdc81SGerd Hoffmann delay_ns = request_count 267663fdc81SGerd Hoffmann ? (NANOSECONDS_PER_SECOND / 100) /* 10 ms interval with active req */ 268663fdc81SGerd Hoffmann : (NANOSECONDS_PER_SECOND); /* 1 sec interval otherwise */ 269663fdc81SGerd Hoffmann timer_mod(poll_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + delay_ns); 270663fdc81SGerd Hoffmann } 271663fdc81SGerd Hoffmann 272663fdc81SGerd Hoffmann static void usb_host_timer(void *opaque) 273663fdc81SGerd Hoffmann { 274663fdc81SGerd Hoffmann struct timeval tv = { 0, 0 }; 275663fdc81SGerd Hoffmann 276663fdc81SGerd Hoffmann libusb_handle_events_timeout(ctx, &tv); 277663fdc81SGerd Hoffmann usb_host_timer_kick(); 278663fdc81SGerd Hoffmann } 279663fdc81SGerd Hoffmann 280a277c3e0SStefan Weil #endif /* !CONFIG_WIN32 */ 281a277c3e0SStefan Weil 2822b2325ffSGerd Hoffmann static int usb_host_init(void) 2832b2325ffSGerd Hoffmann { 284a277c3e0SStefan Weil #ifndef CONFIG_WIN32 2852b2325ffSGerd Hoffmann const struct libusb_pollfd **poll; 286a277c3e0SStefan Weil #endif 2873bf2b3a1SStefan Weil int rc; 2882b2325ffSGerd Hoffmann 2892b2325ffSGerd Hoffmann if (ctx) { 2902b2325ffSGerd Hoffmann return 0; 2912b2325ffSGerd Hoffmann } 2922b2325ffSGerd Hoffmann rc = libusb_init(&ctx); 2932b2325ffSGerd Hoffmann if (rc != 0) { 2942b2325ffSGerd Hoffmann return -1; 2952b2325ffSGerd Hoffmann } 2969d8fa0dfSJohn Thomson #if LIBUSB_API_VERSION >= 0x01000106 2979d8fa0dfSJohn Thomson libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, loglevel); 2989d8fa0dfSJohn Thomson #else 2992b2325ffSGerd Hoffmann libusb_set_debug(ctx, loglevel); 3009d8fa0dfSJohn Thomson #endif 301a277c3e0SStefan Weil #ifdef CONFIG_WIN32 302663fdc81SGerd Hoffmann poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, usb_host_timer, NULL); 303663fdc81SGerd Hoffmann usb_host_timer_kick(); 304a277c3e0SStefan Weil #else 3052b2325ffSGerd Hoffmann libusb_set_pollfd_notifiers(ctx, usb_host_add_fd, 3062b2325ffSGerd Hoffmann usb_host_del_fd, 3072b2325ffSGerd Hoffmann ctx); 3082b2325ffSGerd Hoffmann poll = libusb_get_pollfds(ctx); 3092b2325ffSGerd Hoffmann if (poll) { 3103bf2b3a1SStefan Weil int i; 3112b2325ffSGerd Hoffmann for (i = 0; poll[i] != NULL; i++) { 3122b2325ffSGerd Hoffmann usb_host_add_fd(poll[i]->fd, poll[i]->events, ctx); 3132b2325ffSGerd Hoffmann } 3142b2325ffSGerd Hoffmann } 3152b2325ffSGerd Hoffmann free(poll); 316a277c3e0SStefan Weil #endif 3172b2325ffSGerd Hoffmann return 0; 3182b2325ffSGerd Hoffmann } 3192b2325ffSGerd Hoffmann 3202b2325ffSGerd Hoffmann static int usb_host_get_port(libusb_device *dev, char *port, size_t len) 3212b2325ffSGerd Hoffmann { 3222b2325ffSGerd Hoffmann uint8_t path[7]; 3232b2325ffSGerd Hoffmann size_t off; 3242b2325ffSGerd Hoffmann int rc, i; 3252b2325ffSGerd Hoffmann 326102a3d84SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000102 327bc45de8cSHans de Goede rc = libusb_get_port_numbers(dev, path, 7); 328bc45de8cSHans de Goede #else 3292b2325ffSGerd Hoffmann rc = libusb_get_port_path(ctx, dev, path, 7); 330bc45de8cSHans de Goede #endif 3312b2325ffSGerd Hoffmann if (rc < 0) { 3322b2325ffSGerd Hoffmann return 0; 3332b2325ffSGerd Hoffmann } 3342b2325ffSGerd Hoffmann off = snprintf(port, len, "%d", path[0]); 3352b2325ffSGerd Hoffmann for (i = 1; i < rc; i++) { 3362b2325ffSGerd Hoffmann off += snprintf(port+off, len-off, ".%d", path[i]); 3372b2325ffSGerd Hoffmann } 3382b2325ffSGerd Hoffmann return off; 3392b2325ffSGerd Hoffmann } 3402b2325ffSGerd Hoffmann 3412b2325ffSGerd Hoffmann static void usb_host_libusb_error(const char *func, int rc) 3422b2325ffSGerd Hoffmann { 3432b2325ffSGerd Hoffmann const char *errname; 3442b2325ffSGerd Hoffmann 3452b2325ffSGerd Hoffmann if (rc >= 0) { 3462b2325ffSGerd Hoffmann return; 3472b2325ffSGerd Hoffmann } 3482b2325ffSGerd Hoffmann 3492b2325ffSGerd Hoffmann if (-rc < ARRAY_SIZE(err_names) && err_names[-rc]) { 3502b2325ffSGerd Hoffmann errname = err_names[-rc]; 3512b2325ffSGerd Hoffmann } else { 3522b2325ffSGerd Hoffmann errname = "?"; 3532b2325ffSGerd Hoffmann } 3542e6a0dd1SGonglei error_report("%s: %d [%s]", func, rc, errname); 3552b2325ffSGerd Hoffmann } 3562b2325ffSGerd Hoffmann 3572b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 3582b2325ffSGerd Hoffmann 3592b2325ffSGerd Hoffmann static bool usb_host_use_combining(USBEndpoint *ep) 3602b2325ffSGerd Hoffmann { 3612b2325ffSGerd Hoffmann int type; 3622b2325ffSGerd Hoffmann 3632b2325ffSGerd Hoffmann if (!ep->pipeline) { 3642b2325ffSGerd Hoffmann return false; 3652b2325ffSGerd Hoffmann } 3662b2325ffSGerd Hoffmann if (ep->pid != USB_TOKEN_IN) { 3672b2325ffSGerd Hoffmann return false; 3682b2325ffSGerd Hoffmann } 3692b2325ffSGerd Hoffmann type = usb_ep_get_type(ep->dev, ep->pid, ep->nr); 3702b2325ffSGerd Hoffmann if (type != USB_ENDPOINT_XFER_BULK) { 3712b2325ffSGerd Hoffmann return false; 3722b2325ffSGerd Hoffmann } 3732b2325ffSGerd Hoffmann return true; 3742b2325ffSGerd Hoffmann } 3752b2325ffSGerd Hoffmann 3762b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 3772b2325ffSGerd Hoffmann 3782b2325ffSGerd Hoffmann static USBHostRequest *usb_host_req_alloc(USBHostDevice *s, USBPacket *p, 3792b2325ffSGerd Hoffmann bool in, size_t bufsize) 3802b2325ffSGerd Hoffmann { 3812b2325ffSGerd Hoffmann USBHostRequest *r = g_new0(USBHostRequest, 1); 3822b2325ffSGerd Hoffmann 3832b2325ffSGerd Hoffmann r->host = s; 3842b2325ffSGerd Hoffmann r->p = p; 3852b2325ffSGerd Hoffmann r->in = in; 3862b2325ffSGerd Hoffmann r->xfer = libusb_alloc_transfer(0); 3872b2325ffSGerd Hoffmann if (bufsize) { 3882b2325ffSGerd Hoffmann r->buffer = g_malloc(bufsize); 3892b2325ffSGerd Hoffmann } 3902b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&s->requests, r, next); 391663fdc81SGerd Hoffmann #ifdef CONFIG_WIN32 392663fdc81SGerd Hoffmann request_count++; 393663fdc81SGerd Hoffmann usb_host_timer_kick(); 394663fdc81SGerd Hoffmann #endif 3952b2325ffSGerd Hoffmann return r; 3962b2325ffSGerd Hoffmann } 3972b2325ffSGerd Hoffmann 3982b2325ffSGerd Hoffmann static void usb_host_req_free(USBHostRequest *r) 3992b2325ffSGerd Hoffmann { 400663fdc81SGerd Hoffmann #ifdef CONFIG_WIN32 401663fdc81SGerd Hoffmann request_count--; 402663fdc81SGerd Hoffmann #endif 4032b2325ffSGerd Hoffmann QTAILQ_REMOVE(&r->host->requests, r, next); 4042b2325ffSGerd Hoffmann libusb_free_transfer(r->xfer); 4052b2325ffSGerd Hoffmann g_free(r->buffer); 4062b2325ffSGerd Hoffmann g_free(r); 4072b2325ffSGerd Hoffmann } 4082b2325ffSGerd Hoffmann 4092b2325ffSGerd Hoffmann static USBHostRequest *usb_host_req_find(USBHostDevice *s, USBPacket *p) 4102b2325ffSGerd Hoffmann { 4112b2325ffSGerd Hoffmann USBHostRequest *r; 4122b2325ffSGerd Hoffmann 4132b2325ffSGerd Hoffmann QTAILQ_FOREACH(r, &s->requests, next) { 4142b2325ffSGerd Hoffmann if (r->p == p) { 4152b2325ffSGerd Hoffmann return r; 4162b2325ffSGerd Hoffmann } 4172b2325ffSGerd Hoffmann } 4182b2325ffSGerd Hoffmann return NULL; 4192b2325ffSGerd Hoffmann } 4202b2325ffSGerd Hoffmann 421c16e3664SStefan Weil static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer) 4222b2325ffSGerd Hoffmann { 4232b2325ffSGerd Hoffmann USBHostRequest *r = xfer->user_data; 4242b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 4252b2325ffSGerd Hoffmann bool disconnect = (xfer->status == LIBUSB_TRANSFER_NO_DEVICE); 4262b2325ffSGerd Hoffmann 4272b2325ffSGerd Hoffmann if (r->p == NULL) { 4282b2325ffSGerd Hoffmann goto out; /* request was canceled */ 4292b2325ffSGerd Hoffmann } 4302b2325ffSGerd Hoffmann 4312b2325ffSGerd Hoffmann r->p->status = status_map[xfer->status]; 4322b2325ffSGerd Hoffmann r->p->actual_length = xfer->actual_length; 4332b2325ffSGerd Hoffmann if (r->in && xfer->actual_length) { 4347bacaf5fSYuri Benditovich USBDevice *udev = USB_DEVICE(s); 4357bacaf5fSYuri Benditovich struct libusb_config_descriptor *conf = (void *)r->cbuf; 4362b2325ffSGerd Hoffmann memcpy(r->cbuf, r->buffer + 8, xfer->actual_length); 437b88a3e01SGerd Hoffmann 438b88a3e01SGerd Hoffmann /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices 439b88a3e01SGerd Hoffmann * to work redirected to a not superspeed capable hcd */ 440b88a3e01SGerd Hoffmann if (r->usb3ep0quirk && xfer->actual_length >= 18 && 441b88a3e01SGerd Hoffmann r->cbuf[7] == 9) { 442b88a3e01SGerd Hoffmann r->cbuf[7] = 64; 443b88a3e01SGerd Hoffmann } 4447bacaf5fSYuri Benditovich /* 4457bacaf5fSYuri Benditovich *If this is GET_DESCRIPTOR request for configuration descriptor, 4467bacaf5fSYuri Benditovich * remove 'remote wakeup' flag from it to prevent idle power down 4477bacaf5fSYuri Benditovich * in Windows guest 4487bacaf5fSYuri Benditovich */ 4497bacaf5fSYuri Benditovich if (s->suppress_remote_wake && 4507bacaf5fSYuri Benditovich udev->setup_buf[0] == USB_DIR_IN && 4517bacaf5fSYuri Benditovich udev->setup_buf[1] == USB_REQ_GET_DESCRIPTOR && 4527bacaf5fSYuri Benditovich udev->setup_buf[3] == USB_DT_CONFIG && udev->setup_buf[2] == 0 && 4537bacaf5fSYuri Benditovich xfer->actual_length > 4547bacaf5fSYuri Benditovich offsetof(struct libusb_config_descriptor, bmAttributes) && 4557bacaf5fSYuri Benditovich (conf->bmAttributes & USB_CFG_ATT_WAKEUP)) { 4567bacaf5fSYuri Benditovich trace_usb_host_remote_wakeup_removed(s->bus_num, s->addr); 4577bacaf5fSYuri Benditovich conf->bmAttributes &= ~USB_CFG_ATT_WAKEUP; 4587bacaf5fSYuri Benditovich } 4592b2325ffSGerd Hoffmann } 4602b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 4612b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 4622b2325ffSGerd Hoffmann usb_generic_async_ctrl_complete(USB_DEVICE(s), r->p); 4632b2325ffSGerd Hoffmann 4642b2325ffSGerd Hoffmann out: 4652b2325ffSGerd Hoffmann usb_host_req_free(r); 4662b2325ffSGerd Hoffmann if (disconnect) { 4672b2325ffSGerd Hoffmann usb_host_nodev(s); 4682b2325ffSGerd Hoffmann } 4692b2325ffSGerd Hoffmann } 4702b2325ffSGerd Hoffmann 471c16e3664SStefan Weil static void LIBUSB_CALL usb_host_req_complete_data(struct libusb_transfer *xfer) 4722b2325ffSGerd Hoffmann { 4732b2325ffSGerd Hoffmann USBHostRequest *r = xfer->user_data; 4742b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 4752b2325ffSGerd Hoffmann bool disconnect = (xfer->status == LIBUSB_TRANSFER_NO_DEVICE); 4762b2325ffSGerd Hoffmann 4772b2325ffSGerd Hoffmann if (r->p == NULL) { 4782b2325ffSGerd Hoffmann goto out; /* request was canceled */ 4792b2325ffSGerd Hoffmann } 4802b2325ffSGerd Hoffmann 4812b2325ffSGerd Hoffmann r->p->status = status_map[xfer->status]; 4822b2325ffSGerd Hoffmann if (r->in && xfer->actual_length) { 4832b2325ffSGerd Hoffmann usb_packet_copy(r->p, r->buffer, xfer->actual_length); 4842b2325ffSGerd Hoffmann } 4852b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 4862b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 4872b2325ffSGerd Hoffmann if (usb_host_use_combining(r->p->ep)) { 4882b2325ffSGerd Hoffmann usb_combined_input_packet_complete(USB_DEVICE(s), r->p); 4892b2325ffSGerd Hoffmann } else { 4902b2325ffSGerd Hoffmann usb_packet_complete(USB_DEVICE(s), r->p); 4912b2325ffSGerd Hoffmann } 4922b2325ffSGerd Hoffmann 4932b2325ffSGerd Hoffmann out: 4942b2325ffSGerd Hoffmann usb_host_req_free(r); 4952b2325ffSGerd Hoffmann if (disconnect) { 4962b2325ffSGerd Hoffmann usb_host_nodev(s); 4972b2325ffSGerd Hoffmann } 4982b2325ffSGerd Hoffmann } 4992b2325ffSGerd Hoffmann 5002b2325ffSGerd Hoffmann static void usb_host_req_abort(USBHostRequest *r) 5012b2325ffSGerd Hoffmann { 5022b2325ffSGerd Hoffmann USBHostDevice *s = r->host; 50345ec2671SEd Maste bool inflight = (r->p && r->p->state == USB_PACKET_ASYNC); 5042b2325ffSGerd Hoffmann 5052b2325ffSGerd Hoffmann if (inflight) { 5062b2325ffSGerd Hoffmann r->p->status = USB_RET_NODEV; 5072b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, r->p, 5082b2325ffSGerd Hoffmann r->p->status, r->p->actual_length); 5092b2325ffSGerd Hoffmann if (r->p->ep->nr == 0) { 5102b2325ffSGerd Hoffmann usb_generic_async_ctrl_complete(USB_DEVICE(s), r->p); 5112b2325ffSGerd Hoffmann } else { 5122b2325ffSGerd Hoffmann usb_packet_complete(USB_DEVICE(s), r->p); 5132b2325ffSGerd Hoffmann } 5142b2325ffSGerd Hoffmann r->p = NULL; 5152b2325ffSGerd Hoffmann 5162b2325ffSGerd Hoffmann libusb_cancel_transfer(r->xfer); 5172b2325ffSGerd Hoffmann } 5182b2325ffSGerd Hoffmann } 5192b2325ffSGerd Hoffmann 5202b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 5212b2325ffSGerd Hoffmann 522c16e3664SStefan Weil static void LIBUSB_CALL 523c16e3664SStefan Weil usb_host_req_complete_iso(struct libusb_transfer *transfer) 5242b2325ffSGerd Hoffmann { 5252b2325ffSGerd Hoffmann USBHostIsoXfer *xfer = transfer->user_data; 5262b2325ffSGerd Hoffmann 5272b2325ffSGerd Hoffmann if (!xfer) { 5282b2325ffSGerd Hoffmann /* USBHostIsoXfer released while inflight */ 5292b2325ffSGerd Hoffmann g_free(transfer->buffer); 5302b2325ffSGerd Hoffmann libusb_free_transfer(transfer); 5312b2325ffSGerd Hoffmann return; 5322b2325ffSGerd Hoffmann } 5332b2325ffSGerd Hoffmann 5342b2325ffSGerd Hoffmann QTAILQ_REMOVE(&xfer->ring->inflight, xfer, next); 5352b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&xfer->ring->inflight)) { 5362b2325ffSGerd Hoffmann USBHostDevice *s = xfer->ring->host; 5372b2325ffSGerd Hoffmann trace_usb_host_iso_stop(s->bus_num, s->addr, xfer->ring->ep->nr); 5382b2325ffSGerd Hoffmann } 5392b2325ffSGerd Hoffmann if (xfer->ring->ep->pid == USB_TOKEN_IN) { 5402b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&xfer->ring->copy, xfer, next); 541e206ddfbSGerd Hoffmann usb_wakeup(xfer->ring->ep, 0); 5422b2325ffSGerd Hoffmann } else { 5432b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&xfer->ring->unused, xfer, next); 5442b2325ffSGerd Hoffmann } 5452b2325ffSGerd Hoffmann } 5462b2325ffSGerd Hoffmann 5472b2325ffSGerd Hoffmann static USBHostIsoRing *usb_host_iso_alloc(USBHostDevice *s, USBEndpoint *ep) 5482b2325ffSGerd Hoffmann { 5492b2325ffSGerd Hoffmann USBHostIsoRing *ring = g_new0(USBHostIsoRing, 1); 5502b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 5512b2325ffSGerd Hoffmann /* FIXME: check interval (for now assume one xfer per frame) */ 5522b2325ffSGerd Hoffmann int packets = s->iso_urb_frames; 5532b2325ffSGerd Hoffmann int i; 5542b2325ffSGerd Hoffmann 5552b2325ffSGerd Hoffmann ring->host = s; 5562b2325ffSGerd Hoffmann ring->ep = ep; 5572b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->unused); 5582b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->inflight); 5592b2325ffSGerd Hoffmann QTAILQ_INIT(&ring->copy); 5602b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&s->isorings, ring, next); 5612b2325ffSGerd Hoffmann 5622b2325ffSGerd Hoffmann for (i = 0; i < s->iso_urb_count; i++) { 5632b2325ffSGerd Hoffmann xfer = g_new0(USBHostIsoXfer, 1); 5642b2325ffSGerd Hoffmann xfer->ring = ring; 5652b2325ffSGerd Hoffmann xfer->xfer = libusb_alloc_transfer(packets); 5662b2325ffSGerd Hoffmann xfer->xfer->dev_handle = s->dh; 5672b2325ffSGerd Hoffmann xfer->xfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; 5682b2325ffSGerd Hoffmann 5692b2325ffSGerd Hoffmann xfer->xfer->endpoint = ring->ep->nr; 5702b2325ffSGerd Hoffmann if (ring->ep->pid == USB_TOKEN_IN) { 5712b2325ffSGerd Hoffmann xfer->xfer->endpoint |= USB_DIR_IN; 5722b2325ffSGerd Hoffmann } 5732b2325ffSGerd Hoffmann xfer->xfer->callback = usb_host_req_complete_iso; 5742b2325ffSGerd Hoffmann xfer->xfer->user_data = xfer; 5752b2325ffSGerd Hoffmann 5762b2325ffSGerd Hoffmann xfer->xfer->num_iso_packets = packets; 5772b2325ffSGerd Hoffmann xfer->xfer->length = ring->ep->max_packet_size * packets; 5782b2325ffSGerd Hoffmann xfer->xfer->buffer = g_malloc0(xfer->xfer->length); 5792b2325ffSGerd Hoffmann 5802b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 5812b2325ffSGerd Hoffmann } 5822b2325ffSGerd Hoffmann 5832b2325ffSGerd Hoffmann return ring; 5842b2325ffSGerd Hoffmann } 5852b2325ffSGerd Hoffmann 5862b2325ffSGerd Hoffmann static USBHostIsoRing *usb_host_iso_find(USBHostDevice *s, USBEndpoint *ep) 5872b2325ffSGerd Hoffmann { 5882b2325ffSGerd Hoffmann USBHostIsoRing *ring; 5892b2325ffSGerd Hoffmann 5902b2325ffSGerd Hoffmann QTAILQ_FOREACH(ring, &s->isorings, next) { 5912b2325ffSGerd Hoffmann if (ring->ep == ep) { 5922b2325ffSGerd Hoffmann return ring; 5932b2325ffSGerd Hoffmann } 5942b2325ffSGerd Hoffmann } 5952b2325ffSGerd Hoffmann return NULL; 5962b2325ffSGerd Hoffmann } 5972b2325ffSGerd Hoffmann 5982b2325ffSGerd Hoffmann static void usb_host_iso_reset_xfer(USBHostIsoXfer *xfer) 5992b2325ffSGerd Hoffmann { 6002b2325ffSGerd Hoffmann libusb_set_iso_packet_lengths(xfer->xfer, 6012b2325ffSGerd Hoffmann xfer->ring->ep->max_packet_size); 6022b2325ffSGerd Hoffmann xfer->packet = 0; 6032b2325ffSGerd Hoffmann xfer->copy_complete = false; 6042b2325ffSGerd Hoffmann } 6052b2325ffSGerd Hoffmann 6062b2325ffSGerd Hoffmann static void usb_host_iso_free_xfer(USBHostIsoXfer *xfer, bool inflight) 6072b2325ffSGerd Hoffmann { 6082b2325ffSGerd Hoffmann if (inflight) { 6092b2325ffSGerd Hoffmann xfer->xfer->user_data = NULL; 6102b2325ffSGerd Hoffmann } else { 6112b2325ffSGerd Hoffmann g_free(xfer->xfer->buffer); 6122b2325ffSGerd Hoffmann libusb_free_transfer(xfer->xfer); 6132b2325ffSGerd Hoffmann } 6142b2325ffSGerd Hoffmann g_free(xfer); 6152b2325ffSGerd Hoffmann } 6162b2325ffSGerd Hoffmann 6172b2325ffSGerd Hoffmann static void usb_host_iso_free(USBHostIsoRing *ring) 6182b2325ffSGerd Hoffmann { 6192b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 6202b2325ffSGerd Hoffmann 6212b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->inflight)) != NULL) { 6222b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->inflight, xfer, next); 6232b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, true); 6242b2325ffSGerd Hoffmann } 6252b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->unused)) != NULL) { 6262b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 6272b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, false); 6282b2325ffSGerd Hoffmann } 6292b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->copy)) != NULL) { 6302b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 6312b2325ffSGerd Hoffmann usb_host_iso_free_xfer(xfer, false); 6322b2325ffSGerd Hoffmann } 6332b2325ffSGerd Hoffmann 6342b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->host->isorings, ring, next); 6352b2325ffSGerd Hoffmann g_free(ring); 6362b2325ffSGerd Hoffmann } 6372b2325ffSGerd Hoffmann 6382b2325ffSGerd Hoffmann static void usb_host_iso_free_all(USBHostDevice *s) 6392b2325ffSGerd Hoffmann { 6402b2325ffSGerd Hoffmann USBHostIsoRing *ring; 6412b2325ffSGerd Hoffmann 6422b2325ffSGerd Hoffmann while ((ring = QTAILQ_FIRST(&s->isorings)) != NULL) { 6432b2325ffSGerd Hoffmann usb_host_iso_free(ring); 6442b2325ffSGerd Hoffmann } 6452b2325ffSGerd Hoffmann } 6462b2325ffSGerd Hoffmann 6472b2325ffSGerd Hoffmann static bool usb_host_iso_data_copy(USBHostIsoXfer *xfer, USBPacket *p) 6482b2325ffSGerd Hoffmann { 6492b2325ffSGerd Hoffmann unsigned int psize; 6502b2325ffSGerd Hoffmann unsigned char *buf; 6512b2325ffSGerd Hoffmann 6522b2325ffSGerd Hoffmann buf = libusb_get_iso_packet_buffer_simple(xfer->xfer, xfer->packet); 6532b2325ffSGerd Hoffmann if (p->pid == USB_TOKEN_OUT) { 6542b2325ffSGerd Hoffmann psize = p->iov.size; 6552b2325ffSGerd Hoffmann if (psize > xfer->ring->ep->max_packet_size) { 6562b2325ffSGerd Hoffmann /* should not happen (guest bug) */ 6572b2325ffSGerd Hoffmann psize = xfer->ring->ep->max_packet_size; 6582b2325ffSGerd Hoffmann } 6592b2325ffSGerd Hoffmann xfer->xfer->iso_packet_desc[xfer->packet].length = psize; 6602b2325ffSGerd Hoffmann } else { 6612b2325ffSGerd Hoffmann psize = xfer->xfer->iso_packet_desc[xfer->packet].actual_length; 6622b2325ffSGerd Hoffmann if (psize > p->iov.size) { 6632b2325ffSGerd Hoffmann /* should not happen (guest bug) */ 6642b2325ffSGerd Hoffmann psize = p->iov.size; 6652b2325ffSGerd Hoffmann } 6662b2325ffSGerd Hoffmann } 6672b2325ffSGerd Hoffmann usb_packet_copy(p, buf, psize); 6682b2325ffSGerd Hoffmann xfer->packet++; 6692b2325ffSGerd Hoffmann xfer->copy_complete = (xfer->packet == xfer->xfer->num_iso_packets); 6702b2325ffSGerd Hoffmann return xfer->copy_complete; 6712b2325ffSGerd Hoffmann } 6722b2325ffSGerd Hoffmann 6732b2325ffSGerd Hoffmann static void usb_host_iso_data_in(USBHostDevice *s, USBPacket *p) 6742b2325ffSGerd Hoffmann { 6752b2325ffSGerd Hoffmann USBHostIsoRing *ring; 6762b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 6772b2325ffSGerd Hoffmann bool disconnect = false; 6782b2325ffSGerd Hoffmann int rc; 6792b2325ffSGerd Hoffmann 6802b2325ffSGerd Hoffmann ring = usb_host_iso_find(s, p->ep); 6812b2325ffSGerd Hoffmann if (ring == NULL) { 6822b2325ffSGerd Hoffmann ring = usb_host_iso_alloc(s, p->ep); 6832b2325ffSGerd Hoffmann } 6842b2325ffSGerd Hoffmann 6852b2325ffSGerd Hoffmann /* copy data to guest */ 6862b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->copy); 6872b2325ffSGerd Hoffmann if (xfer != NULL) { 6882b2325ffSGerd Hoffmann if (usb_host_iso_data_copy(xfer, p)) { 6892b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 6902b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 6912b2325ffSGerd Hoffmann } 6922b2325ffSGerd Hoffmann } 6932b2325ffSGerd Hoffmann 6942b2325ffSGerd Hoffmann /* submit empty bufs to host */ 6952b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->unused)) != NULL) { 6962b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 6972b2325ffSGerd Hoffmann usb_host_iso_reset_xfer(xfer); 6982b2325ffSGerd Hoffmann rc = libusb_submit_transfer(xfer->xfer); 6992b2325ffSGerd Hoffmann if (rc != 0) { 7002b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_submit_transfer [iso]", rc); 7012b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 7022b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 7032b2325ffSGerd Hoffmann disconnect = true; 7042b2325ffSGerd Hoffmann } 7052b2325ffSGerd Hoffmann break; 7062b2325ffSGerd Hoffmann } 7072b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 7082b2325ffSGerd Hoffmann trace_usb_host_iso_start(s->bus_num, s->addr, p->ep->nr); 7092b2325ffSGerd Hoffmann } 7102b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->inflight, xfer, next); 7112b2325ffSGerd Hoffmann } 7122b2325ffSGerd Hoffmann 7132b2325ffSGerd Hoffmann if (disconnect) { 7142b2325ffSGerd Hoffmann usb_host_nodev(s); 7152b2325ffSGerd Hoffmann } 7162b2325ffSGerd Hoffmann } 7172b2325ffSGerd Hoffmann 7182b2325ffSGerd Hoffmann static void usb_host_iso_data_out(USBHostDevice *s, USBPacket *p) 7192b2325ffSGerd Hoffmann { 7202b2325ffSGerd Hoffmann USBHostIsoRing *ring; 7212b2325ffSGerd Hoffmann USBHostIsoXfer *xfer; 7222b2325ffSGerd Hoffmann bool disconnect = false; 7232b2325ffSGerd Hoffmann int rc, filled = 0; 7242b2325ffSGerd Hoffmann 7252b2325ffSGerd Hoffmann ring = usb_host_iso_find(s, p->ep); 7262b2325ffSGerd Hoffmann if (ring == NULL) { 7272b2325ffSGerd Hoffmann ring = usb_host_iso_alloc(s, p->ep); 7282b2325ffSGerd Hoffmann } 7292b2325ffSGerd Hoffmann 7302b2325ffSGerd Hoffmann /* copy data from guest */ 7312b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->copy); 7322b2325ffSGerd Hoffmann while (xfer != NULL && xfer->copy_complete) { 7332b2325ffSGerd Hoffmann filled++; 7342b2325ffSGerd Hoffmann xfer = QTAILQ_NEXT(xfer, next); 7352b2325ffSGerd Hoffmann } 7362b2325ffSGerd Hoffmann if (xfer == NULL) { 7372b2325ffSGerd Hoffmann xfer = QTAILQ_FIRST(&ring->unused); 7382b2325ffSGerd Hoffmann if (xfer == NULL) { 7392b2325ffSGerd Hoffmann trace_usb_host_iso_out_of_bufs(s->bus_num, s->addr, p->ep->nr); 7402b2325ffSGerd Hoffmann return; 7412b2325ffSGerd Hoffmann } 7422b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->unused, xfer, next); 7432b2325ffSGerd Hoffmann usb_host_iso_reset_xfer(xfer); 7442b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->copy, xfer, next); 7452b2325ffSGerd Hoffmann } 7462b2325ffSGerd Hoffmann usb_host_iso_data_copy(xfer, p); 7472b2325ffSGerd Hoffmann 7482b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 7492b2325ffSGerd Hoffmann /* wait until half of our buffers are filled 7502b2325ffSGerd Hoffmann before kicking the iso out stream */ 7512b2325ffSGerd Hoffmann if (filled*2 < s->iso_urb_count) { 7522b2325ffSGerd Hoffmann return; 7532b2325ffSGerd Hoffmann } 7542b2325ffSGerd Hoffmann } 7552b2325ffSGerd Hoffmann 7562b2325ffSGerd Hoffmann /* submit filled bufs to host */ 7572b2325ffSGerd Hoffmann while ((xfer = QTAILQ_FIRST(&ring->copy)) != NULL && 7582b2325ffSGerd Hoffmann xfer->copy_complete) { 7592b2325ffSGerd Hoffmann QTAILQ_REMOVE(&ring->copy, xfer, next); 7602b2325ffSGerd Hoffmann rc = libusb_submit_transfer(xfer->xfer); 7612b2325ffSGerd Hoffmann if (rc != 0) { 7622b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_submit_transfer [iso]", rc); 7632b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->unused, xfer, next); 7642b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 7652b2325ffSGerd Hoffmann disconnect = true; 7662b2325ffSGerd Hoffmann } 7672b2325ffSGerd Hoffmann break; 7682b2325ffSGerd Hoffmann } 7692b2325ffSGerd Hoffmann if (QTAILQ_EMPTY(&ring->inflight)) { 7702b2325ffSGerd Hoffmann trace_usb_host_iso_start(s->bus_num, s->addr, p->ep->nr); 7712b2325ffSGerd Hoffmann } 7722b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&ring->inflight, xfer, next); 7732b2325ffSGerd Hoffmann } 7742b2325ffSGerd Hoffmann 7752b2325ffSGerd Hoffmann if (disconnect) { 7762b2325ffSGerd Hoffmann usb_host_nodev(s); 7772b2325ffSGerd Hoffmann } 7782b2325ffSGerd Hoffmann } 7792b2325ffSGerd Hoffmann 7802b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 7812b2325ffSGerd Hoffmann 782b88a3e01SGerd Hoffmann static void usb_host_speed_compat(USBHostDevice *s) 783c3268cc1SGerd Hoffmann { 784b88a3e01SGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 785c3268cc1SGerd Hoffmann struct libusb_config_descriptor *conf; 786c3268cc1SGerd Hoffmann const struct libusb_interface_descriptor *intf; 787c3268cc1SGerd Hoffmann const struct libusb_endpoint_descriptor *endp; 788322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 789b88a3e01SGerd Hoffmann struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp; 790b88a3e01SGerd Hoffmann #endif 791b88a3e01SGerd Hoffmann bool compat_high = true; 792b88a3e01SGerd Hoffmann bool compat_full = true; 793c3268cc1SGerd Hoffmann uint8_t type; 794c3268cc1SGerd Hoffmann int rc, c, i, a, e; 795c3268cc1SGerd Hoffmann 796c3268cc1SGerd Hoffmann for (c = 0;; c++) { 797c3268cc1SGerd Hoffmann rc = libusb_get_config_descriptor(s->dev, c, &conf); 798c3268cc1SGerd Hoffmann if (rc != 0) { 799c3268cc1SGerd Hoffmann break; 800c3268cc1SGerd Hoffmann } 801c3268cc1SGerd Hoffmann for (i = 0; i < conf->bNumInterfaces; i++) { 802c3268cc1SGerd Hoffmann for (a = 0; a < conf->interface[i].num_altsetting; a++) { 803c3268cc1SGerd Hoffmann intf = &conf->interface[i].altsetting[a]; 804b7b2a60bSGerd Hoffmann 805b7b2a60bSGerd Hoffmann if (intf->bInterfaceClass == LIBUSB_CLASS_MASS_STORAGE && 806b7b2a60bSGerd Hoffmann intf->bInterfaceSubClass == 6) { /* SCSI */ 807b7b2a60bSGerd Hoffmann udev->flags |= (1 << USB_DEV_FLAG_IS_SCSI_STORAGE); 808b7b2a60bSGerd Hoffmann break; 809b7b2a60bSGerd Hoffmann } 810b7b2a60bSGerd Hoffmann 811c3268cc1SGerd Hoffmann for (e = 0; e < intf->bNumEndpoints; e++) { 812c3268cc1SGerd Hoffmann endp = &intf->endpoint[e]; 813c3268cc1SGerd Hoffmann type = endp->bmAttributes & 0x3; 814c3268cc1SGerd Hoffmann switch (type) { 815c3268cc1SGerd Hoffmann case 0x01: /* ISO */ 816b88a3e01SGerd Hoffmann compat_full = false; 817b88a3e01SGerd Hoffmann compat_high = false; 818b88a3e01SGerd Hoffmann break; 819b88a3e01SGerd Hoffmann case 0x02: /* BULK */ 820322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 821b88a3e01SGerd Hoffmann rc = libusb_get_ss_endpoint_companion_descriptor 822b88a3e01SGerd Hoffmann (ctx, endp, &endp_ss_comp); 823b88a3e01SGerd Hoffmann if (rc == LIBUSB_SUCCESS) { 8246a711234SGerd Hoffmann int streams = endp_ss_comp->bmAttributes & 0x1f; 8256a711234SGerd Hoffmann if (streams) { 826b88a3e01SGerd Hoffmann compat_full = false; 827b88a3e01SGerd Hoffmann compat_high = false; 828b88a3e01SGerd Hoffmann } 8296a711234SGerd Hoffmann libusb_free_ss_endpoint_companion_descriptor 8306a711234SGerd Hoffmann (endp_ss_comp); 8316a711234SGerd Hoffmann } 832b88a3e01SGerd Hoffmann #endif 833b88a3e01SGerd Hoffmann break; 834c3268cc1SGerd Hoffmann case 0x03: /* INTERRUPT */ 835c3268cc1SGerd Hoffmann if (endp->wMaxPacketSize > 64) { 836b88a3e01SGerd Hoffmann compat_full = false; 837b88a3e01SGerd Hoffmann } 838b88a3e01SGerd Hoffmann if (endp->wMaxPacketSize > 1024) { 839b88a3e01SGerd Hoffmann compat_high = false; 840c3268cc1SGerd Hoffmann } 841c3268cc1SGerd Hoffmann break; 842c3268cc1SGerd Hoffmann } 843c3268cc1SGerd Hoffmann } 844c3268cc1SGerd Hoffmann } 845c3268cc1SGerd Hoffmann } 846c3268cc1SGerd Hoffmann libusb_free_config_descriptor(conf); 847c3268cc1SGerd Hoffmann } 848b88a3e01SGerd Hoffmann 849b88a3e01SGerd Hoffmann udev->speedmask = (1 << udev->speed); 850b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_SUPER && compat_high) { 85179ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_HIGH; 852b88a3e01SGerd Hoffmann } 853b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_SUPER && compat_full) { 85479ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_FULL; 855b88a3e01SGerd Hoffmann } 856b88a3e01SGerd Hoffmann if (udev->speed == USB_SPEED_HIGH && compat_full) { 85779ae25afSGerd Hoffmann udev->speedmask |= USB_SPEED_MASK_FULL; 858b88a3e01SGerd Hoffmann } 859c3268cc1SGerd Hoffmann } 860c3268cc1SGerd Hoffmann 8612b2325ffSGerd Hoffmann static void usb_host_ep_update(USBHostDevice *s) 8622b2325ffSGerd Hoffmann { 8632b2325ffSGerd Hoffmann static const char *tname[] = { 8642b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_CONTROL] = "control", 8652b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_ISOC] = "isoc", 8662b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_BULK] = "bulk", 8672b2325ffSGerd Hoffmann [USB_ENDPOINT_XFER_INT] = "int", 8682b2325ffSGerd Hoffmann }; 8692b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 8702b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 8712b2325ffSGerd Hoffmann const struct libusb_interface_descriptor *intf; 8722b2325ffSGerd Hoffmann const struct libusb_endpoint_descriptor *endp; 873322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 874b664b80fSHans de Goede struct libusb_ss_endpoint_companion_descriptor *endp_ss_comp; 875b664b80fSHans de Goede #endif 8762b2325ffSGerd Hoffmann uint8_t devep, type; 8770dbe4768SNick Rosbrook int pid, ep, alt; 8782b2325ffSGerd Hoffmann int rc, i, e; 8792b2325ffSGerd Hoffmann 8802b2325ffSGerd Hoffmann usb_ep_reset(udev); 8812b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 8822b2325ffSGerd Hoffmann if (rc != 0) { 8832b2325ffSGerd Hoffmann return; 8842b2325ffSGerd Hoffmann } 8852b2325ffSGerd Hoffmann trace_usb_host_parse_config(s->bus_num, s->addr, 8862b2325ffSGerd Hoffmann conf->bConfigurationValue, true); 8872b2325ffSGerd Hoffmann 8882b2325ffSGerd Hoffmann for (i = 0; i < conf->bNumInterfaces; i++) { 8890dbe4768SNick Rosbrook /* 8900dbe4768SNick Rosbrook * The udev->altsetting array indexes alternate settings 8910dbe4768SNick Rosbrook * by the interface number. Get the 0th alternate setting 8920dbe4768SNick Rosbrook * first so that we can grab the interface number, and 8930dbe4768SNick Rosbrook * then correct the alternate setting value if necessary. 8940dbe4768SNick Rosbrook */ 8950dbe4768SNick Rosbrook intf = &conf->interface[i].altsetting[0]; 8960dbe4768SNick Rosbrook alt = udev->altsetting[intf->bInterfaceNumber]; 8970dbe4768SNick Rosbrook 8980dbe4768SNick Rosbrook if (alt != 0) { 8990dbe4768SNick Rosbrook assert(alt < conf->interface[i].num_altsetting); 9000dbe4768SNick Rosbrook intf = &conf->interface[i].altsetting[alt]; 9010dbe4768SNick Rosbrook } 9020dbe4768SNick Rosbrook 9032b2325ffSGerd Hoffmann trace_usb_host_parse_interface(s->bus_num, s->addr, 9042b2325ffSGerd Hoffmann intf->bInterfaceNumber, 9052b2325ffSGerd Hoffmann intf->bAlternateSetting, true); 9062b2325ffSGerd Hoffmann for (e = 0; e < intf->bNumEndpoints; e++) { 9072b2325ffSGerd Hoffmann endp = &intf->endpoint[e]; 9082b2325ffSGerd Hoffmann 9092b2325ffSGerd Hoffmann devep = endp->bEndpointAddress; 9102b2325ffSGerd Hoffmann pid = (devep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; 9112b2325ffSGerd Hoffmann ep = devep & 0xf; 9122b2325ffSGerd Hoffmann type = endp->bmAttributes & 0x3; 9132b2325ffSGerd Hoffmann 9142b2325ffSGerd Hoffmann if (ep == 0) { 9152b2325ffSGerd Hoffmann trace_usb_host_parse_error(s->bus_num, s->addr, 9162b2325ffSGerd Hoffmann "invalid endpoint address"); 9172b2325ffSGerd Hoffmann return; 9182b2325ffSGerd Hoffmann } 9192b2325ffSGerd Hoffmann if (usb_ep_get_type(udev, pid, ep) != USB_ENDPOINT_XFER_INVALID) { 9202b2325ffSGerd Hoffmann trace_usb_host_parse_error(s->bus_num, s->addr, 9212b2325ffSGerd Hoffmann "duplicate endpoint address"); 9222b2325ffSGerd Hoffmann return; 9232b2325ffSGerd Hoffmann } 9242b2325ffSGerd Hoffmann 9252b2325ffSGerd Hoffmann trace_usb_host_parse_endpoint(s->bus_num, s->addr, ep, 9262b2325ffSGerd Hoffmann (devep & USB_DIR_IN) ? "in" : "out", 9272b2325ffSGerd Hoffmann tname[type], true); 9282b2325ffSGerd Hoffmann usb_ep_set_max_packet_size(udev, pid, ep, 9292b2325ffSGerd Hoffmann endp->wMaxPacketSize); 9302b2325ffSGerd Hoffmann usb_ep_set_type(udev, pid, ep, type); 9312b2325ffSGerd Hoffmann usb_ep_set_ifnum(udev, pid, ep, i); 9322b2325ffSGerd Hoffmann usb_ep_set_halted(udev, pid, ep, 0); 933322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 934b664b80fSHans de Goede if (type == LIBUSB_TRANSFER_TYPE_BULK && 935b664b80fSHans de Goede libusb_get_ss_endpoint_companion_descriptor(ctx, endp, 936b664b80fSHans de Goede &endp_ss_comp) == LIBUSB_SUCCESS) { 937b664b80fSHans de Goede usb_ep_set_max_streams(udev, pid, ep, 938b664b80fSHans de Goede endp_ss_comp->bmAttributes); 939b664b80fSHans de Goede libusb_free_ss_endpoint_companion_descriptor(endp_ss_comp); 940b664b80fSHans de Goede } 941b664b80fSHans de Goede #endif 9422b2325ffSGerd Hoffmann } 9432b2325ffSGerd Hoffmann } 9442b2325ffSGerd Hoffmann 9452b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 9462b2325ffSGerd Hoffmann } 9472b2325ffSGerd Hoffmann 9489f815e83SGerd Hoffmann static int usb_host_open(USBHostDevice *s, libusb_device *dev, int hostfd) 9492b2325ffSGerd Hoffmann { 9502b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 951202d69a7SGerd Hoffmann int libusb_speed; 9529f815e83SGerd Hoffmann int bus_num = 0; 9539f815e83SGerd Hoffmann int addr = 0; 9542b2325ffSGerd Hoffmann int rc; 9557d553f27SGonglei Error *local_err = NULL; 9562b2325ffSGerd Hoffmann 9573280ea8eSGerd Hoffmann if (s->bh_postld_pending) { 9583280ea8eSGerd Hoffmann return -1; 9593280ea8eSGerd Hoffmann } 9602b2325ffSGerd Hoffmann if (s->dh != NULL) { 9612b2325ffSGerd Hoffmann goto fail; 9622b2325ffSGerd Hoffmann } 9639f815e83SGerd Hoffmann 9649f815e83SGerd Hoffmann if (dev) { 9659f815e83SGerd Hoffmann bus_num = libusb_get_bus_number(dev); 9669f815e83SGerd Hoffmann addr = libusb_get_device_address(dev); 9679f815e83SGerd Hoffmann trace_usb_host_open_started(bus_num, addr); 9689f815e83SGerd Hoffmann 9692b2325ffSGerd Hoffmann rc = libusb_open(dev, &s->dh); 9702b2325ffSGerd Hoffmann if (rc != 0) { 9712b2325ffSGerd Hoffmann goto fail; 9722b2325ffSGerd Hoffmann } 9739f815e83SGerd Hoffmann } else { 974631009e7SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) 9759f815e83SGerd Hoffmann trace_usb_host_open_hostfd(hostfd); 9769f815e83SGerd Hoffmann 9779f815e83SGerd Hoffmann rc = libusb_wrap_sys_device(ctx, hostfd, &s->dh); 9789f815e83SGerd Hoffmann if (rc != 0) { 9799f815e83SGerd Hoffmann goto fail; 9809f815e83SGerd Hoffmann } 9819f815e83SGerd Hoffmann s->hostfd = hostfd; 9829f815e83SGerd Hoffmann dev = libusb_get_device(s->dh); 9839f815e83SGerd Hoffmann bus_num = libusb_get_bus_number(dev); 9849f815e83SGerd Hoffmann addr = libusb_get_device_address(dev); 9859f815e83SGerd Hoffmann #else 9869f815e83SGerd Hoffmann g_assert_not_reached(); 9879f815e83SGerd Hoffmann #endif 9889f815e83SGerd Hoffmann } 9892b2325ffSGerd Hoffmann 9902b2325ffSGerd Hoffmann s->dev = dev; 9912b2325ffSGerd Hoffmann s->bus_num = bus_num; 9922b2325ffSGerd Hoffmann s->addr = addr; 993f34d5c75SHans de Goede 994f34d5c75SHans de Goede usb_host_detach_kernel(s); 995f34d5c75SHans de Goede 996f34d5c75SHans de Goede libusb_get_device_descriptor(dev, &s->ddesc); 9972b2325ffSGerd Hoffmann usb_host_get_port(s->dev, s->port, sizeof(s->port)); 9982b2325ffSGerd Hoffmann 9992b2325ffSGerd Hoffmann usb_ep_init(udev); 10002b2325ffSGerd Hoffmann usb_host_ep_update(s); 10012b2325ffSGerd Hoffmann 1002202d69a7SGerd Hoffmann libusb_speed = libusb_get_device_speed(dev); 1003a3c27ea0SFabrice Fontaine #if LIBUSB_API_VERSION >= 0x01000107 && defined(CONFIG_LINUX) && \ 1004a3c27ea0SFabrice Fontaine defined(USBDEVFS_GET_SPEED) 1005202d69a7SGerd Hoffmann if (hostfd && libusb_speed == 0) { 1006202d69a7SGerd Hoffmann /* 1007202d69a7SGerd Hoffmann * Workaround libusb bug: libusb_get_device_speed() does not 1008202d69a7SGerd Hoffmann * work for libusb_wrap_sys_device() devices in v1.0.23. 1009202d69a7SGerd Hoffmann * 1010202d69a7SGerd Hoffmann * Speeds are defined in linux/usb/ch9.h, file not included 1011202d69a7SGerd Hoffmann * due to name conflicts. 1012202d69a7SGerd Hoffmann */ 1013202d69a7SGerd Hoffmann int rc = ioctl(hostfd, USBDEVFS_GET_SPEED, NULL); 1014202d69a7SGerd Hoffmann switch (rc) { 1015202d69a7SGerd Hoffmann case 1: /* low */ 1016202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_LOW; 1017202d69a7SGerd Hoffmann break; 1018202d69a7SGerd Hoffmann case 2: /* full */ 1019202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_FULL; 1020202d69a7SGerd Hoffmann break; 1021202d69a7SGerd Hoffmann case 3: /* high */ 1022202d69a7SGerd Hoffmann case 4: /* wireless */ 1023202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_HIGH; 1024202d69a7SGerd Hoffmann break; 1025202d69a7SGerd Hoffmann case 5: /* super */ 1026202d69a7SGerd Hoffmann libusb_speed = LIBUSB_SPEED_SUPER; 1027202d69a7SGerd Hoffmann break; 10282980a316SGerd Hoffmann case 6: /* super plus */ 10292980a316SGerd Hoffmann #ifdef HAVE_SUPER_PLUS 10302980a316SGerd Hoffmann libusb_speed = LIBUSB_SPEED_SUPER_PLUS; 10312980a316SGerd Hoffmann #else 10322980a316SGerd Hoffmann libusb_speed = LIBUSB_SPEED_SUPER; 10332980a316SGerd Hoffmann #endif 10342980a316SGerd Hoffmann break; 1035202d69a7SGerd Hoffmann } 1036202d69a7SGerd Hoffmann } 1037202d69a7SGerd Hoffmann #endif 1038202d69a7SGerd Hoffmann udev->speed = speed_map[libusb_speed]; 1039b88a3e01SGerd Hoffmann usb_host_speed_compat(s); 10402b2325ffSGerd Hoffmann 10412b2325ffSGerd Hoffmann if (s->ddesc.iProduct) { 10422b2325ffSGerd Hoffmann libusb_get_string_descriptor_ascii(s->dh, s->ddesc.iProduct, 10432b2325ffSGerd Hoffmann (unsigned char *)udev->product_desc, 10442b2325ffSGerd Hoffmann sizeof(udev->product_desc)); 10452b2325ffSGerd Hoffmann } else { 10462b2325ffSGerd Hoffmann snprintf(udev->product_desc, sizeof(udev->product_desc), 10472b2325ffSGerd Hoffmann "host:%d.%d", bus_num, addr); 10482b2325ffSGerd Hoffmann } 10492b2325ffSGerd Hoffmann 10507d553f27SGonglei usb_device_attach(udev, &local_err); 10517d553f27SGonglei if (local_err) { 1052565f65d2SMarkus Armbruster error_report_err(local_err); 10532b2325ffSGerd Hoffmann goto fail; 10542b2325ffSGerd Hoffmann } 10552b2325ffSGerd Hoffmann 10562b2325ffSGerd Hoffmann trace_usb_host_open_success(bus_num, addr); 10572b2325ffSGerd Hoffmann return 0; 10582b2325ffSGerd Hoffmann 10592b2325ffSGerd Hoffmann fail: 10602b2325ffSGerd Hoffmann trace_usb_host_open_failure(bus_num, addr); 10612b2325ffSGerd Hoffmann if (s->dh != NULL) { 10626110ce59SLin Ma usb_host_release_interfaces(s); 10636110ce59SLin Ma libusb_reset_device(s->dh); 10646110ce59SLin Ma usb_host_attach_kernel(s); 10652b2325ffSGerd Hoffmann libusb_close(s->dh); 10662b2325ffSGerd Hoffmann s->dh = NULL; 10672b2325ffSGerd Hoffmann s->dev = NULL; 10682b2325ffSGerd Hoffmann } 10692b2325ffSGerd Hoffmann return -1; 10702b2325ffSGerd Hoffmann } 10712b2325ffSGerd Hoffmann 10722b2325ffSGerd Hoffmann static void usb_host_abort_xfers(USBHostDevice *s) 10732b2325ffSGerd Hoffmann { 10742b2325ffSGerd Hoffmann USBHostRequest *r, *rtmp; 107554cdfe51SGerd Hoffmann int limit = 100; 10762b2325ffSGerd Hoffmann 10772b2325ffSGerd Hoffmann QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { 10782b2325ffSGerd Hoffmann usb_host_req_abort(r); 10792b2325ffSGerd Hoffmann } 108076d0a936SGerd Hoffmann 108176d0a936SGerd Hoffmann while (QTAILQ_FIRST(&s->requests) != NULL) { 108276d0a936SGerd Hoffmann struct timeval tv; 108376d0a936SGerd Hoffmann memset(&tv, 0, sizeof(tv)); 108476d0a936SGerd Hoffmann tv.tv_usec = 2500; 108576d0a936SGerd Hoffmann libusb_handle_events_timeout(ctx, &tv); 108654cdfe51SGerd Hoffmann if (--limit == 0) { 108754cdfe51SGerd Hoffmann /* 108854cdfe51SGerd Hoffmann * Don't wait forever for libusb calling the complete 108954cdfe51SGerd Hoffmann * callback (which will unlink and free the request). 109054cdfe51SGerd Hoffmann * 109154cdfe51SGerd Hoffmann * Leaking memory here, to make sure libusb will not 109254cdfe51SGerd Hoffmann * access memory which we have released already. 109354cdfe51SGerd Hoffmann */ 109454cdfe51SGerd Hoffmann QTAILQ_FOREACH_SAFE(r, &s->requests, next, rtmp) { 109554cdfe51SGerd Hoffmann QTAILQ_REMOVE(&s->requests, r, next); 109654cdfe51SGerd Hoffmann } 109754cdfe51SGerd Hoffmann return; 109854cdfe51SGerd Hoffmann } 109976d0a936SGerd Hoffmann } 11002b2325ffSGerd Hoffmann } 11012b2325ffSGerd Hoffmann 11022b2325ffSGerd Hoffmann static int usb_host_close(USBHostDevice *s) 11032b2325ffSGerd Hoffmann { 11042b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 11052b2325ffSGerd Hoffmann 11062b2325ffSGerd Hoffmann if (s->dh == NULL) { 11072b2325ffSGerd Hoffmann return -1; 11082b2325ffSGerd Hoffmann } 11092b2325ffSGerd Hoffmann 11102b2325ffSGerd Hoffmann trace_usb_host_close(s->bus_num, s->addr); 11112b2325ffSGerd Hoffmann 11122b2325ffSGerd Hoffmann usb_host_abort_xfers(s); 11132b2325ffSGerd Hoffmann usb_host_iso_free_all(s); 11142b2325ffSGerd Hoffmann 11152b2325ffSGerd Hoffmann if (udev->attached) { 11162b2325ffSGerd Hoffmann usb_device_detach(udev); 11172b2325ffSGerd Hoffmann } 11182b2325ffSGerd Hoffmann 11192b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 11202b2325ffSGerd Hoffmann libusb_reset_device(s->dh); 11212b2325ffSGerd Hoffmann usb_host_attach_kernel(s); 11222b2325ffSGerd Hoffmann libusb_close(s->dh); 11232b2325ffSGerd Hoffmann s->dh = NULL; 11242b2325ffSGerd Hoffmann s->dev = NULL; 11252b2325ffSGerd Hoffmann 11269f815e83SGerd Hoffmann if (s->hostfd != -1) { 11279f815e83SGerd Hoffmann close(s->hostfd); 11289f815e83SGerd Hoffmann s->hostfd = -1; 11299f815e83SGerd Hoffmann } 11309f815e83SGerd Hoffmann 11312b2325ffSGerd Hoffmann usb_host_auto_check(NULL); 11322b2325ffSGerd Hoffmann return 0; 11332b2325ffSGerd Hoffmann } 11342b2325ffSGerd Hoffmann 11352b2325ffSGerd Hoffmann static void usb_host_nodev_bh(void *opaque) 11362b2325ffSGerd Hoffmann { 11372b2325ffSGerd Hoffmann USBHostDevice *s = opaque; 11382b2325ffSGerd Hoffmann usb_host_close(s); 11392b2325ffSGerd Hoffmann } 11402b2325ffSGerd Hoffmann 11412b2325ffSGerd Hoffmann static void usb_host_nodev(USBHostDevice *s) 11422b2325ffSGerd Hoffmann { 114395efb20cSGerd Hoffmann if (!s->bh_nodev) { 114495efb20cSGerd Hoffmann s->bh_nodev = qemu_bh_new(usb_host_nodev_bh, s); 11452b2325ffSGerd Hoffmann } 114695efb20cSGerd Hoffmann qemu_bh_schedule(s->bh_nodev); 11472b2325ffSGerd Hoffmann } 11482b2325ffSGerd Hoffmann 11492b2325ffSGerd Hoffmann static void usb_host_exit_notifier(struct Notifier *n, void *data) 11502b2325ffSGerd Hoffmann { 11512b2325ffSGerd Hoffmann USBHostDevice *s = container_of(n, USBHostDevice, exit); 11522b2325ffSGerd Hoffmann 11532b2325ffSGerd Hoffmann if (s->dh) { 115476d0a936SGerd Hoffmann usb_host_abort_xfers(s); 11552b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 11565621d045Slinzhecheng libusb_reset_device(s->dh); 11572b2325ffSGerd Hoffmann usb_host_attach_kernel(s); 11585621d045Slinzhecheng libusb_close(s->dh); 11592b2325ffSGerd Hoffmann } 11602b2325ffSGerd Hoffmann } 11612b2325ffSGerd Hoffmann 1162e058fa2dSGerd Hoffmann static libusb_device *usb_host_find_ref(int bus, int addr) 1163e058fa2dSGerd Hoffmann { 1164e058fa2dSGerd Hoffmann libusb_device **devs = NULL; 1165e058fa2dSGerd Hoffmann libusb_device *ret = NULL; 1166e058fa2dSGerd Hoffmann int i, n; 1167e058fa2dSGerd Hoffmann 1168e058fa2dSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 1169e058fa2dSGerd Hoffmann for (i = 0; i < n; i++) { 1170e058fa2dSGerd Hoffmann if (libusb_get_bus_number(devs[i]) == bus && 1171e058fa2dSGerd Hoffmann libusb_get_device_address(devs[i]) == addr) { 1172e058fa2dSGerd Hoffmann ret = libusb_ref_device(devs[i]); 1173e058fa2dSGerd Hoffmann break; 1174e058fa2dSGerd Hoffmann } 1175e058fa2dSGerd Hoffmann } 1176e058fa2dSGerd Hoffmann libusb_free_device_list(devs, 1); 1177e058fa2dSGerd Hoffmann return ret; 1178e058fa2dSGerd Hoffmann } 1179e058fa2dSGerd Hoffmann 11802aa76dc1SGonglei static void usb_host_realize(USBDevice *udev, Error **errp) 11812b2325ffSGerd Hoffmann { 11822b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 1183e058fa2dSGerd Hoffmann libusb_device *ldev; 1184e058fa2dSGerd Hoffmann int rc; 11852b2325ffSGerd Hoffmann 11869f815e83SGerd Hoffmann if (usb_host_init() != 0) { 11879f815e83SGerd Hoffmann error_setg(errp, "failed to init libusb"); 11889f815e83SGerd Hoffmann return; 11899f815e83SGerd Hoffmann } 1190f3cda6e0SGerd Hoffmann if (s->match.vendor_id > 0xffff) { 11912aa76dc1SGonglei error_setg(errp, "vendorid out of range"); 11922aa76dc1SGonglei return; 1193f3cda6e0SGerd Hoffmann } 1194f3cda6e0SGerd Hoffmann if (s->match.product_id > 0xffff) { 11952aa76dc1SGonglei error_setg(errp, "productid out of range"); 11962aa76dc1SGonglei return; 1197f3cda6e0SGerd Hoffmann } 1198f3cda6e0SGerd Hoffmann if (s->match.addr > 127) { 11992aa76dc1SGonglei error_setg(errp, "hostaddr out of range"); 12002aa76dc1SGonglei return; 1201f3cda6e0SGerd Hoffmann } 1202f3cda6e0SGerd Hoffmann 12032b2325ffSGerd Hoffmann loglevel = s->loglevel; 1204628e5485SGerd Hoffmann udev->flags |= (1 << USB_DEV_FLAG_IS_HOST); 12052b2325ffSGerd Hoffmann udev->auto_attach = 0; 12062b2325ffSGerd Hoffmann QTAILQ_INIT(&s->requests); 12072b2325ffSGerd Hoffmann QTAILQ_INIT(&s->isorings); 12089f815e83SGerd Hoffmann s->hostfd = -1; 12092b2325ffSGerd Hoffmann 1210631009e7SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 && !defined(CONFIG_WIN32) 12119f815e83SGerd Hoffmann if (s->hostdevice) { 12129f815e83SGerd Hoffmann int fd; 12139f815e83SGerd Hoffmann s->needs_autoscan = false; 1214448058aaSDaniel P. Berrangé fd = qemu_open_old(s->hostdevice, O_RDWR); 12159f815e83SGerd Hoffmann if (fd < 0) { 12169f815e83SGerd Hoffmann error_setg_errno(errp, errno, "failed to open %s", s->hostdevice); 12179f815e83SGerd Hoffmann return; 12189f815e83SGerd Hoffmann } 12199f815e83SGerd Hoffmann rc = usb_host_open(s, NULL, fd); 12209f815e83SGerd Hoffmann if (rc < 0) { 12219f815e83SGerd Hoffmann error_setg(errp, "failed to open host usb device %s", s->hostdevice); 12229f815e83SGerd Hoffmann return; 12239f815e83SGerd Hoffmann } 12249f815e83SGerd Hoffmann } else 12259f815e83SGerd Hoffmann #endif 1226e058fa2dSGerd Hoffmann if (s->match.addr && s->match.bus_num && 1227e058fa2dSGerd Hoffmann !s->match.vendor_id && 1228e058fa2dSGerd Hoffmann !s->match.product_id && 1229e058fa2dSGerd Hoffmann !s->match.port) { 1230e058fa2dSGerd Hoffmann s->needs_autoscan = false; 1231e058fa2dSGerd Hoffmann ldev = usb_host_find_ref(s->match.bus_num, 1232e058fa2dSGerd Hoffmann s->match.addr); 1233e058fa2dSGerd Hoffmann if (!ldev) { 1234e058fa2dSGerd Hoffmann error_setg(errp, "failed to find host usb device %d:%d", 1235e058fa2dSGerd Hoffmann s->match.bus_num, s->match.addr); 1236e058fa2dSGerd Hoffmann return; 1237e058fa2dSGerd Hoffmann } 12389f815e83SGerd Hoffmann rc = usb_host_open(s, ldev, 0); 1239e058fa2dSGerd Hoffmann libusb_unref_device(ldev); 1240e058fa2dSGerd Hoffmann if (rc < 0) { 1241e058fa2dSGerd Hoffmann error_setg(errp, "failed to open host usb device %d:%d", 1242e058fa2dSGerd Hoffmann s->match.bus_num, s->match.addr); 1243e058fa2dSGerd Hoffmann return; 1244e058fa2dSGerd Hoffmann } 1245e058fa2dSGerd Hoffmann } else { 1246e058fa2dSGerd Hoffmann s->needs_autoscan = true; 12472b2325ffSGerd Hoffmann QTAILQ_INSERT_TAIL(&hostdevs, s, next); 12482b2325ffSGerd Hoffmann usb_host_auto_check(NULL); 12492b2325ffSGerd Hoffmann } 12502b2325ffSGerd Hoffmann 1251e058fa2dSGerd Hoffmann s->exit.notify = usb_host_exit_notifier; 1252e058fa2dSGerd Hoffmann qemu_add_exit_notifier(&s->exit); 1253e058fa2dSGerd Hoffmann } 1254e058fa2dSGerd Hoffmann 1255e6adae52SGonglei static void usb_host_instance_init(Object *obj) 1256e6adae52SGonglei { 1257e6adae52SGonglei USBDevice *udev = USB_DEVICE(obj); 1258e6adae52SGonglei USBHostDevice *s = USB_HOST_DEVICE(udev); 1259e6adae52SGonglei 1260e6adae52SGonglei device_add_bootindex_property(obj, &s->bootindex, 1261e6adae52SGonglei "bootindex", NULL, 126240c2281cSMarkus Armbruster &udev->qdev); 1263e6adae52SGonglei } 1264e6adae52SGonglei 1265b69c3c21SMarkus Armbruster static void usb_host_unrealize(USBDevice *udev) 12662b2325ffSGerd Hoffmann { 12672b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 12682b2325ffSGerd Hoffmann 12692b2325ffSGerd Hoffmann qemu_remove_exit_notifier(&s->exit); 1270e058fa2dSGerd Hoffmann if (s->needs_autoscan) { 12712b2325ffSGerd Hoffmann QTAILQ_REMOVE(&hostdevs, s, next); 1272e058fa2dSGerd Hoffmann } 12732b2325ffSGerd Hoffmann usb_host_close(s); 12742b2325ffSGerd Hoffmann } 12752b2325ffSGerd Hoffmann 12762b2325ffSGerd Hoffmann static void usb_host_cancel_packet(USBDevice *udev, USBPacket *p) 12772b2325ffSGerd Hoffmann { 12782b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 12792b2325ffSGerd Hoffmann USBHostRequest *r; 12802b2325ffSGerd Hoffmann 12812b2325ffSGerd Hoffmann if (p->combined) { 12822b2325ffSGerd Hoffmann usb_combined_packet_cancel(udev, p); 12832b2325ffSGerd Hoffmann return; 12842b2325ffSGerd Hoffmann } 12852b2325ffSGerd Hoffmann 12862b2325ffSGerd Hoffmann trace_usb_host_req_canceled(s->bus_num, s->addr, p); 12872b2325ffSGerd Hoffmann 12882b2325ffSGerd Hoffmann r = usb_host_req_find(s, p); 12892b2325ffSGerd Hoffmann if (r && r->p) { 12902b2325ffSGerd Hoffmann r->p = NULL; /* mark as dead */ 12912b2325ffSGerd Hoffmann libusb_cancel_transfer(r->xfer); 12922b2325ffSGerd Hoffmann } 12932b2325ffSGerd Hoffmann } 12942b2325ffSGerd Hoffmann 12952b2325ffSGerd Hoffmann static void usb_host_detach_kernel(USBHostDevice *s) 12962b2325ffSGerd Hoffmann { 12972b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 12982b2325ffSGerd Hoffmann int rc, i; 12992b2325ffSGerd Hoffmann 13002b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 13012b2325ffSGerd Hoffmann if (rc != 0) { 13022b2325ffSGerd Hoffmann return; 13032b2325ffSGerd Hoffmann } 1304896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13052b2325ffSGerd Hoffmann rc = libusb_kernel_driver_active(s->dh, i); 13062b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_kernel_driver_active", rc); 13072b2325ffSGerd Hoffmann if (rc != 1) { 1308933d2d4bSlinzhecheng if (rc == 0) { 1309933d2d4bSlinzhecheng s->ifs[i].detached = true; 1310933d2d4bSlinzhecheng } 13112b2325ffSGerd Hoffmann continue; 13122b2325ffSGerd Hoffmann } 13132b2325ffSGerd Hoffmann trace_usb_host_detach_kernel(s->bus_num, s->addr, i); 13142b2325ffSGerd Hoffmann rc = libusb_detach_kernel_driver(s->dh, i); 13152b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_detach_kernel_driver", rc); 13162b2325ffSGerd Hoffmann s->ifs[i].detached = true; 13172b2325ffSGerd Hoffmann } 13182b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 13192b2325ffSGerd Hoffmann } 13202b2325ffSGerd Hoffmann 13212b2325ffSGerd Hoffmann static void usb_host_attach_kernel(USBHostDevice *s) 13222b2325ffSGerd Hoffmann { 13232b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 13242b2325ffSGerd Hoffmann int rc, i; 13252b2325ffSGerd Hoffmann 13262b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 13272b2325ffSGerd Hoffmann if (rc != 0) { 13282b2325ffSGerd Hoffmann return; 13292b2325ffSGerd Hoffmann } 1330896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13312b2325ffSGerd Hoffmann if (!s->ifs[i].detached) { 13322b2325ffSGerd Hoffmann continue; 13332b2325ffSGerd Hoffmann } 13342b2325ffSGerd Hoffmann trace_usb_host_attach_kernel(s->bus_num, s->addr, i); 13352b2325ffSGerd Hoffmann libusb_attach_kernel_driver(s->dh, i); 13362b2325ffSGerd Hoffmann s->ifs[i].detached = false; 13372b2325ffSGerd Hoffmann } 13382b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 13392b2325ffSGerd Hoffmann } 13402b2325ffSGerd Hoffmann 13412b2325ffSGerd Hoffmann static int usb_host_claim_interfaces(USBHostDevice *s, int configuration) 13422b2325ffSGerd Hoffmann { 13432b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 13442b2325ffSGerd Hoffmann struct libusb_config_descriptor *conf; 1345896b6757SSamuel Brian int rc, i, claimed; 13462b2325ffSGerd Hoffmann 13472b2325ffSGerd Hoffmann for (i = 0; i < USB_MAX_INTERFACES; i++) { 13482b2325ffSGerd Hoffmann udev->altsetting[i] = 0; 13492b2325ffSGerd Hoffmann } 13502b2325ffSGerd Hoffmann udev->ninterfaces = 0; 13512b2325ffSGerd Hoffmann udev->configuration = 0; 13522b2325ffSGerd Hoffmann 13532b2325ffSGerd Hoffmann usb_host_detach_kernel(s); 13542b2325ffSGerd Hoffmann 13552b2325ffSGerd Hoffmann rc = libusb_get_active_config_descriptor(s->dev, &conf); 13562b2325ffSGerd Hoffmann if (rc != 0) { 13571294ca79SHans de Goede if (rc == LIBUSB_ERROR_NOT_FOUND) { 13581294ca79SHans de Goede /* address state - ignore */ 13591294ca79SHans de Goede return USB_RET_SUCCESS; 13601294ca79SHans de Goede } 13612b2325ffSGerd Hoffmann return USB_RET_STALL; 13622b2325ffSGerd Hoffmann } 13632b2325ffSGerd Hoffmann 1364896b6757SSamuel Brian claimed = 0; 1365896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13662b2325ffSGerd Hoffmann trace_usb_host_claim_interface(s->bus_num, s->addr, configuration, i); 13672b2325ffSGerd Hoffmann rc = libusb_claim_interface(s->dh, i); 1368896b6757SSamuel Brian if (rc == 0) { 13692b2325ffSGerd Hoffmann s->ifs[i].claimed = true; 1370896b6757SSamuel Brian if (++claimed == conf->bNumInterfaces) { 1371896b6757SSamuel Brian break; 1372896b6757SSamuel Brian } 1373896b6757SSamuel Brian } 1374896b6757SSamuel Brian } 1375896b6757SSamuel Brian if (claimed != conf->bNumInterfaces) { 1376896b6757SSamuel Brian return USB_RET_STALL; 13772b2325ffSGerd Hoffmann } 13782b2325ffSGerd Hoffmann 13792b2325ffSGerd Hoffmann udev->ninterfaces = conf->bNumInterfaces; 13802b2325ffSGerd Hoffmann udev->configuration = configuration; 13812b2325ffSGerd Hoffmann 13822b2325ffSGerd Hoffmann libusb_free_config_descriptor(conf); 13832b2325ffSGerd Hoffmann return USB_RET_SUCCESS; 13842b2325ffSGerd Hoffmann } 13852b2325ffSGerd Hoffmann 13862b2325ffSGerd Hoffmann static void usb_host_release_interfaces(USBHostDevice *s) 13872b2325ffSGerd Hoffmann { 13882b2325ffSGerd Hoffmann int i, rc; 13892b2325ffSGerd Hoffmann 1390896b6757SSamuel Brian for (i = 0; i < USB_MAX_INTERFACES; i++) { 13912b2325ffSGerd Hoffmann if (!s->ifs[i].claimed) { 13922b2325ffSGerd Hoffmann continue; 13932b2325ffSGerd Hoffmann } 13942b2325ffSGerd Hoffmann trace_usb_host_release_interface(s->bus_num, s->addr, i); 13952b2325ffSGerd Hoffmann rc = libusb_release_interface(s->dh, i); 13962b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_release_interface", rc); 13972b2325ffSGerd Hoffmann s->ifs[i].claimed = false; 13982b2325ffSGerd Hoffmann } 13992b2325ffSGerd Hoffmann } 14002b2325ffSGerd Hoffmann 14012b2325ffSGerd Hoffmann static void usb_host_set_address(USBHostDevice *s, int addr) 14022b2325ffSGerd Hoffmann { 14032b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 14042b2325ffSGerd Hoffmann 14052b2325ffSGerd Hoffmann trace_usb_host_set_address(s->bus_num, s->addr, addr); 14062b2325ffSGerd Hoffmann udev->addr = addr; 14072b2325ffSGerd Hoffmann } 14082b2325ffSGerd Hoffmann 14092b2325ffSGerd Hoffmann static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p) 14102b2325ffSGerd Hoffmann { 1411bfe44898SGerd Hoffmann int rc = 0; 14122b2325ffSGerd Hoffmann 14132b2325ffSGerd Hoffmann trace_usb_host_set_config(s->bus_num, s->addr, config); 14142b2325ffSGerd Hoffmann 14152b2325ffSGerd Hoffmann usb_host_release_interfaces(s); 1416bfe44898SGerd Hoffmann if (s->ddesc.bNumConfigurations != 1) { 14172b2325ffSGerd Hoffmann rc = libusb_set_configuration(s->dh, config); 14182b2325ffSGerd Hoffmann if (rc != 0) { 14192b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_set_configuration", rc); 14202b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 14212b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 14222b2325ffSGerd Hoffmann usb_host_nodev(s); 14232b2325ffSGerd Hoffmann } 14242b2325ffSGerd Hoffmann return; 14252b2325ffSGerd Hoffmann } 1426bfe44898SGerd Hoffmann } 14272b2325ffSGerd Hoffmann p->status = usb_host_claim_interfaces(s, config); 14282b2325ffSGerd Hoffmann if (p->status != USB_RET_SUCCESS) { 14292b2325ffSGerd Hoffmann return; 14302b2325ffSGerd Hoffmann } 14312b2325ffSGerd Hoffmann usb_host_ep_update(s); 14322b2325ffSGerd Hoffmann } 14332b2325ffSGerd Hoffmann 14342b2325ffSGerd Hoffmann static void usb_host_set_interface(USBHostDevice *s, int iface, int alt, 14352b2325ffSGerd Hoffmann USBPacket *p) 14362b2325ffSGerd Hoffmann { 14372b2325ffSGerd Hoffmann USBDevice *udev = USB_DEVICE(s); 14382b2325ffSGerd Hoffmann int rc; 14392b2325ffSGerd Hoffmann 14402b2325ffSGerd Hoffmann trace_usb_host_set_interface(s->bus_num, s->addr, iface, alt); 14412b2325ffSGerd Hoffmann 14422b2325ffSGerd Hoffmann usb_host_iso_free_all(s); 14432b2325ffSGerd Hoffmann 14442b2325ffSGerd Hoffmann if (iface >= USB_MAX_INTERFACES) { 14452b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 14462b2325ffSGerd Hoffmann return; 14472b2325ffSGerd Hoffmann } 14482b2325ffSGerd Hoffmann 14492b2325ffSGerd Hoffmann rc = libusb_set_interface_alt_setting(s->dh, iface, alt); 14502b2325ffSGerd Hoffmann if (rc != 0) { 14512b2325ffSGerd Hoffmann usb_host_libusb_error("libusb_set_interface_alt_setting", rc); 14522b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 14532b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 14542b2325ffSGerd Hoffmann usb_host_nodev(s); 14552b2325ffSGerd Hoffmann } 14562b2325ffSGerd Hoffmann return; 14572b2325ffSGerd Hoffmann } 14582b2325ffSGerd Hoffmann 14592b2325ffSGerd Hoffmann udev->altsetting[iface] = alt; 14602b2325ffSGerd Hoffmann usb_host_ep_update(s); 14612b2325ffSGerd Hoffmann } 14622b2325ffSGerd Hoffmann 14632b2325ffSGerd Hoffmann static void usb_host_handle_control(USBDevice *udev, USBPacket *p, 14642b2325ffSGerd Hoffmann int request, int value, int index, 14652b2325ffSGerd Hoffmann int length, uint8_t *data) 14662b2325ffSGerd Hoffmann { 14672b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 14682b2325ffSGerd Hoffmann USBHostRequest *r; 14692b2325ffSGerd Hoffmann int rc; 14702b2325ffSGerd Hoffmann 14712b2325ffSGerd Hoffmann trace_usb_host_req_control(s->bus_num, s->addr, p, request, value, index); 14722b2325ffSGerd Hoffmann 14732b2325ffSGerd Hoffmann if (s->dh == NULL) { 14742b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 14752b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14762b2325ffSGerd Hoffmann return; 14772b2325ffSGerd Hoffmann } 14782b2325ffSGerd Hoffmann 14792b2325ffSGerd Hoffmann switch (request) { 14802b2325ffSGerd Hoffmann case DeviceOutRequest | USB_REQ_SET_ADDRESS: 14812b2325ffSGerd Hoffmann usb_host_set_address(s, value); 14822b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14832b2325ffSGerd Hoffmann return; 14842b2325ffSGerd Hoffmann 14852b2325ffSGerd Hoffmann case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: 14862b2325ffSGerd Hoffmann usb_host_set_config(s, value & 0xff, p); 14872b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14882b2325ffSGerd Hoffmann return; 14892b2325ffSGerd Hoffmann 14902b2325ffSGerd Hoffmann case InterfaceOutRequest | USB_REQ_SET_INTERFACE: 14912b2325ffSGerd Hoffmann usb_host_set_interface(s, index, value, p); 14922b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 14932b2325ffSGerd Hoffmann return; 14942b2325ffSGerd Hoffmann 14952b2325ffSGerd Hoffmann case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: 14962b2325ffSGerd Hoffmann if (value == 0) { /* clear halt */ 14972b2325ffSGerd Hoffmann int pid = (index & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT; 14982b2325ffSGerd Hoffmann libusb_clear_halt(s->dh, index); 14992b2325ffSGerd Hoffmann usb_ep_set_halted(udev, pid, index & 0x0f, 0); 15002b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 15012b2325ffSGerd Hoffmann return; 15022b2325ffSGerd Hoffmann } 15032b2325ffSGerd Hoffmann } 15042b2325ffSGerd Hoffmann 15052b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, (request >> 8) & USB_DIR_IN, length + 8); 15062b2325ffSGerd Hoffmann r->cbuf = data; 15072b2325ffSGerd Hoffmann r->clen = length; 15082b2325ffSGerd Hoffmann memcpy(r->buffer, udev->setup_buf, 8); 15092b2325ffSGerd Hoffmann if (!r->in) { 15102b2325ffSGerd Hoffmann memcpy(r->buffer + 8, r->cbuf, r->clen); 15112b2325ffSGerd Hoffmann } 15122b2325ffSGerd Hoffmann 1513b88a3e01SGerd Hoffmann /* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices 1514b88a3e01SGerd Hoffmann * to work redirected to a not superspeed capable hcd */ 1515a9be4e7cSGerd Hoffmann if ((udev->speedmask & USB_SPEED_MASK_SUPER) && 151672517114Slijun !(udev->port->speedmask & USB_SPEED_MASK_SUPER) && 1517b88a3e01SGerd Hoffmann request == 0x8006 && value == 0x100 && index == 0) { 1518b88a3e01SGerd Hoffmann r->usb3ep0quirk = true; 1519b88a3e01SGerd Hoffmann } 1520b88a3e01SGerd Hoffmann 15212b2325ffSGerd Hoffmann libusb_fill_control_transfer(r->xfer, s->dh, r->buffer, 15222b2325ffSGerd Hoffmann usb_host_req_complete_ctrl, r, 15232b2325ffSGerd Hoffmann CONTROL_TIMEOUT); 15242b2325ffSGerd Hoffmann rc = libusb_submit_transfer(r->xfer); 15252b2325ffSGerd Hoffmann if (rc != 0) { 15262b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 15272b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 15282b2325ffSGerd Hoffmann p->status, p->actual_length); 15292b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 15302b2325ffSGerd Hoffmann usb_host_nodev(s); 15312b2325ffSGerd Hoffmann } 15322b2325ffSGerd Hoffmann return; 15332b2325ffSGerd Hoffmann } 15342b2325ffSGerd Hoffmann 15352b2325ffSGerd Hoffmann p->status = USB_RET_ASYNC; 15362b2325ffSGerd Hoffmann } 15372b2325ffSGerd Hoffmann 15382b2325ffSGerd Hoffmann static void usb_host_handle_data(USBDevice *udev, USBPacket *p) 15392b2325ffSGerd Hoffmann { 15402b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 15412b2325ffSGerd Hoffmann USBHostRequest *r; 15422b2325ffSGerd Hoffmann size_t size; 15432b2325ffSGerd Hoffmann int ep, rc; 15442b2325ffSGerd Hoffmann 15452b2325ffSGerd Hoffmann if (usb_host_use_combining(p->ep) && p->state == USB_PACKET_SETUP) { 15462b2325ffSGerd Hoffmann p->status = USB_RET_ADD_TO_QUEUE; 15472b2325ffSGerd Hoffmann return; 15482b2325ffSGerd Hoffmann } 15492b2325ffSGerd Hoffmann 15502b2325ffSGerd Hoffmann trace_usb_host_req_data(s->bus_num, s->addr, p, 15512b2325ffSGerd Hoffmann p->pid == USB_TOKEN_IN, 15522b2325ffSGerd Hoffmann p->ep->nr, p->iov.size); 15532b2325ffSGerd Hoffmann 15542b2325ffSGerd Hoffmann if (s->dh == NULL) { 15552b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 15562b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 15572b2325ffSGerd Hoffmann return; 15582b2325ffSGerd Hoffmann } 15592b2325ffSGerd Hoffmann if (p->ep->halted) { 15602b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 15612b2325ffSGerd Hoffmann trace_usb_host_req_emulated(s->bus_num, s->addr, p, p->status); 15622b2325ffSGerd Hoffmann return; 15632b2325ffSGerd Hoffmann } 15642b2325ffSGerd Hoffmann 15652b2325ffSGerd Hoffmann switch (usb_ep_get_type(udev, p->pid, p->ep->nr)) { 15662b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_BULK: 15672b2325ffSGerd Hoffmann size = usb_packet_size(p); 15682b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, p->pid == USB_TOKEN_IN, size); 15692b2325ffSGerd Hoffmann if (!r->in) { 15702b2325ffSGerd Hoffmann usb_packet_copy(p, r->buffer, size); 15712b2325ffSGerd Hoffmann } 15722b2325ffSGerd Hoffmann ep = p->ep->nr | (r->in ? USB_DIR_IN : 0); 15738d1bd3c9SHans de Goede if (p->stream) { 1574322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 15758d1bd3c9SHans de Goede libusb_fill_bulk_stream_transfer(r->xfer, s->dh, ep, p->stream, 15768d1bd3c9SHans de Goede r->buffer, size, 15778d1bd3c9SHans de Goede usb_host_req_complete_data, r, 15788d1bd3c9SHans de Goede BULK_TIMEOUT); 15798d1bd3c9SHans de Goede #else 15808d1bd3c9SHans de Goede usb_host_req_free(r); 15818d1bd3c9SHans de Goede p->status = USB_RET_STALL; 15828d1bd3c9SHans de Goede return; 15838d1bd3c9SHans de Goede #endif 15848d1bd3c9SHans de Goede } else { 15852b2325ffSGerd Hoffmann libusb_fill_bulk_transfer(r->xfer, s->dh, ep, 15862b2325ffSGerd Hoffmann r->buffer, size, 15872b2325ffSGerd Hoffmann usb_host_req_complete_data, r, 15882b2325ffSGerd Hoffmann BULK_TIMEOUT); 15898d1bd3c9SHans de Goede } 15902b2325ffSGerd Hoffmann break; 15912b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_INT: 15922b2325ffSGerd Hoffmann r = usb_host_req_alloc(s, p, p->pid == USB_TOKEN_IN, p->iov.size); 15932b2325ffSGerd Hoffmann if (!r->in) { 15942b2325ffSGerd Hoffmann usb_packet_copy(p, r->buffer, p->iov.size); 15952b2325ffSGerd Hoffmann } 15962b2325ffSGerd Hoffmann ep = p->ep->nr | (r->in ? USB_DIR_IN : 0); 15972b2325ffSGerd Hoffmann libusb_fill_interrupt_transfer(r->xfer, s->dh, ep, 15982b2325ffSGerd Hoffmann r->buffer, p->iov.size, 15992b2325ffSGerd Hoffmann usb_host_req_complete_data, r, 16002b2325ffSGerd Hoffmann INTR_TIMEOUT); 16012b2325ffSGerd Hoffmann break; 16022b2325ffSGerd Hoffmann case USB_ENDPOINT_XFER_ISOC: 16032b2325ffSGerd Hoffmann if (p->pid == USB_TOKEN_IN) { 16042b2325ffSGerd Hoffmann usb_host_iso_data_in(s, p); 16052b2325ffSGerd Hoffmann } else { 16062b2325ffSGerd Hoffmann usb_host_iso_data_out(s, p); 16072b2325ffSGerd Hoffmann } 16082b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 16092b2325ffSGerd Hoffmann p->status, p->actual_length); 16102b2325ffSGerd Hoffmann return; 16112b2325ffSGerd Hoffmann default: 16122b2325ffSGerd Hoffmann p->status = USB_RET_STALL; 16132b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 16142b2325ffSGerd Hoffmann p->status, p->actual_length); 16152b2325ffSGerd Hoffmann return; 16162b2325ffSGerd Hoffmann } 16172b2325ffSGerd Hoffmann 16182b2325ffSGerd Hoffmann rc = libusb_submit_transfer(r->xfer); 16192b2325ffSGerd Hoffmann if (rc != 0) { 16202b2325ffSGerd Hoffmann p->status = USB_RET_NODEV; 16212b2325ffSGerd Hoffmann trace_usb_host_req_complete(s->bus_num, s->addr, p, 16222b2325ffSGerd Hoffmann p->status, p->actual_length); 16232b2325ffSGerd Hoffmann if (rc == LIBUSB_ERROR_NO_DEVICE) { 16242b2325ffSGerd Hoffmann usb_host_nodev(s); 16252b2325ffSGerd Hoffmann } 16262b2325ffSGerd Hoffmann return; 16272b2325ffSGerd Hoffmann } 16282b2325ffSGerd Hoffmann 16292b2325ffSGerd Hoffmann p->status = USB_RET_ASYNC; 16302b2325ffSGerd Hoffmann } 16312b2325ffSGerd Hoffmann 16322b2325ffSGerd Hoffmann static void usb_host_flush_ep_queue(USBDevice *dev, USBEndpoint *ep) 16332b2325ffSGerd Hoffmann { 16342b2325ffSGerd Hoffmann if (usb_host_use_combining(ep)) { 16352b2325ffSGerd Hoffmann usb_ep_combine_input_packets(ep); 16362b2325ffSGerd Hoffmann } 16372b2325ffSGerd Hoffmann } 16382b2325ffSGerd Hoffmann 16392b2325ffSGerd Hoffmann static void usb_host_handle_reset(USBDevice *udev) 16402b2325ffSGerd Hoffmann { 16412b2325ffSGerd Hoffmann USBHostDevice *s = USB_HOST_DEVICE(udev); 16425af35d7fSHans de Goede int rc; 16432b2325ffSGerd Hoffmann 16441dfe2b91SGerd Hoffmann if (!s->allow_one_guest_reset && !s->allow_all_guest_resets) { 1645ba4c735bSAlexander Kappner return; 1646ba4c735bSAlexander Kappner } 16471dfe2b91SGerd Hoffmann if (!s->allow_all_guest_resets && udev->addr == 0) { 164865f14ab9SGerd Hoffmann return; 164965f14ab9SGerd Hoffmann } 1650ba4c735bSAlexander Kappner 16512b2325ffSGerd Hoffmann trace_usb_host_reset(s->bus_num, s->addr); 16522b2325ffSGerd Hoffmann 16535af35d7fSHans de Goede rc = libusb_reset_device(s->dh); 16545af35d7fSHans de Goede if (rc != 0) { 16555af35d7fSHans de Goede usb_host_nodev(s); 16562b2325ffSGerd Hoffmann } 16572b2325ffSGerd Hoffmann } 16582b2325ffSGerd Hoffmann 165956a9f180SHans de Goede static int usb_host_alloc_streams(USBDevice *udev, USBEndpoint **eps, 166056a9f180SHans de Goede int nr_eps, int streams) 166156a9f180SHans de Goede { 1662322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 166356a9f180SHans de Goede USBHostDevice *s = USB_HOST_DEVICE(udev); 166456a9f180SHans de Goede unsigned char endpoints[30]; 166556a9f180SHans de Goede int i, rc; 166656a9f180SHans de Goede 166756a9f180SHans de Goede for (i = 0; i < nr_eps; i++) { 166856a9f180SHans de Goede endpoints[i] = eps[i]->nr; 166956a9f180SHans de Goede if (eps[i]->pid == USB_TOKEN_IN) { 167056a9f180SHans de Goede endpoints[i] |= 0x80; 167156a9f180SHans de Goede } 167256a9f180SHans de Goede } 167356a9f180SHans de Goede rc = libusb_alloc_streams(s->dh, streams, endpoints, nr_eps); 167456a9f180SHans de Goede if (rc < 0) { 167556a9f180SHans de Goede usb_host_libusb_error("libusb_alloc_streams", rc); 167656a9f180SHans de Goede } else if (rc != streams) { 16772e6a0dd1SGonglei error_report("libusb_alloc_streams: got less streams " 16782e6a0dd1SGonglei "then requested %d < %d", rc, streams); 167956a9f180SHans de Goede } 168056a9f180SHans de Goede 168156a9f180SHans de Goede return (rc == streams) ? 0 : -1; 168256a9f180SHans de Goede #else 16832e6a0dd1SGonglei error_report("libusb_alloc_streams: error not implemented"); 168456a9f180SHans de Goede return -1; 168556a9f180SHans de Goede #endif 168656a9f180SHans de Goede } 168756a9f180SHans de Goede 168856a9f180SHans de Goede static void usb_host_free_streams(USBDevice *udev, USBEndpoint **eps, 168956a9f180SHans de Goede int nr_eps) 169056a9f180SHans de Goede { 1691322fd1f4SGerd Hoffmann #ifdef HAVE_STREAMS 169256a9f180SHans de Goede USBHostDevice *s = USB_HOST_DEVICE(udev); 169356a9f180SHans de Goede unsigned char endpoints[30]; 169456a9f180SHans de Goede int i; 169556a9f180SHans de Goede 169656a9f180SHans de Goede for (i = 0; i < nr_eps; i++) { 169756a9f180SHans de Goede endpoints[i] = eps[i]->nr; 169856a9f180SHans de Goede if (eps[i]->pid == USB_TOKEN_IN) { 169956a9f180SHans de Goede endpoints[i] |= 0x80; 170056a9f180SHans de Goede } 170156a9f180SHans de Goede } 170256a9f180SHans de Goede libusb_free_streams(s->dh, endpoints, nr_eps); 170356a9f180SHans de Goede #endif 170456a9f180SHans de Goede } 170556a9f180SHans de Goede 170695efb20cSGerd Hoffmann /* 170795efb20cSGerd Hoffmann * This is *NOT* about restoring state. We have absolutely no idea 170895efb20cSGerd Hoffmann * what state the host device is in at the moment and whenever it is 1709*ae420c95SCai Huoqing * still present in the first place. Attempting to continue where we 171095efb20cSGerd Hoffmann * left off is impossible. 171195efb20cSGerd Hoffmann * 1712b6af0975SDaniel P. Berrange * What we are going to do here is emulate a surprise removal of 171395efb20cSGerd Hoffmann * the usb device passed through, then kick host scan so the device 171495efb20cSGerd Hoffmann * will get re-attached (and re-initialized by the guest) in case it 171595efb20cSGerd Hoffmann * is still present. 171695efb20cSGerd Hoffmann * 171795efb20cSGerd Hoffmann * As the device removal will change the state of other devices (usb 171895efb20cSGerd Hoffmann * host controller, most likely interrupt controller too) we have to 171995efb20cSGerd Hoffmann * wait with it until *all* vmstate is loaded. Thus post_load just 172095efb20cSGerd Hoffmann * kicks a bottom half which then does the actual work. 172195efb20cSGerd Hoffmann */ 172295efb20cSGerd Hoffmann static void usb_host_post_load_bh(void *opaque) 172395efb20cSGerd Hoffmann { 172495efb20cSGerd Hoffmann USBHostDevice *dev = opaque; 172595efb20cSGerd Hoffmann USBDevice *udev = USB_DEVICE(dev); 172695efb20cSGerd Hoffmann 172795efb20cSGerd Hoffmann if (dev->dh != NULL) { 172895efb20cSGerd Hoffmann usb_host_close(dev); 172995efb20cSGerd Hoffmann } 173095efb20cSGerd Hoffmann if (udev->attached) { 173195efb20cSGerd Hoffmann usb_device_detach(udev); 173295efb20cSGerd Hoffmann } 17333280ea8eSGerd Hoffmann dev->bh_postld_pending = false; 173495efb20cSGerd Hoffmann usb_host_auto_check(NULL); 173595efb20cSGerd Hoffmann } 173695efb20cSGerd Hoffmann 173795efb20cSGerd Hoffmann static int usb_host_post_load(void *opaque, int version_id) 173895efb20cSGerd Hoffmann { 173995efb20cSGerd Hoffmann USBHostDevice *dev = opaque; 174095efb20cSGerd Hoffmann 174195efb20cSGerd Hoffmann if (!dev->bh_postld) { 174295efb20cSGerd Hoffmann dev->bh_postld = qemu_bh_new(usb_host_post_load_bh, dev); 174395efb20cSGerd Hoffmann } 174495efb20cSGerd Hoffmann qemu_bh_schedule(dev->bh_postld); 17453280ea8eSGerd Hoffmann dev->bh_postld_pending = true; 174695efb20cSGerd Hoffmann return 0; 174795efb20cSGerd Hoffmann } 174895efb20cSGerd Hoffmann 17492b2325ffSGerd Hoffmann static const VMStateDescription vmstate_usb_host = { 17502b2325ffSGerd Hoffmann .name = "usb-host", 175195efb20cSGerd Hoffmann .version_id = 1, 175295efb20cSGerd Hoffmann .minimum_version_id = 1, 175395efb20cSGerd Hoffmann .post_load = usb_host_post_load, 17542b2325ffSGerd Hoffmann .fields = (VMStateField[]) { 17552b2325ffSGerd Hoffmann VMSTATE_USB_DEVICE(parent_obj, USBHostDevice), 17562b2325ffSGerd Hoffmann VMSTATE_END_OF_LIST() 17572b2325ffSGerd Hoffmann } 17582b2325ffSGerd Hoffmann }; 17592b2325ffSGerd Hoffmann 17602b2325ffSGerd Hoffmann static Property usb_host_dev_properties[] = { 17612b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("hostbus", USBHostDevice, match.bus_num, 0), 17622b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("hostaddr", USBHostDevice, match.addr, 0), 17632b2325ffSGerd Hoffmann DEFINE_PROP_STRING("hostport", USBHostDevice, match.port), 1764c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("vendorid", USBHostDevice, match.vendor_id, 0), 1765c7bcc85dSPaolo Bonzini DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), 17669f815e83SGerd Hoffmann #if LIBUSB_API_VERSION >= 0x01000107 17679f815e83SGerd Hoffmann DEFINE_PROP_STRING("hostdevice", USBHostDevice, hostdevice), 17689f815e83SGerd Hoffmann #endif 17692b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), 17702b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), 17711dfe2b91SGerd Hoffmann DEFINE_PROP_BOOL("guest-reset", USBHostDevice, 17721dfe2b91SGerd Hoffmann allow_one_guest_reset, true), 17731dfe2b91SGerd Hoffmann DEFINE_PROP_BOOL("guest-resets-all", USBHostDevice, 17741dfe2b91SGerd Hoffmann allow_all_guest_resets, false), 17752b2325ffSGerd Hoffmann DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel, 17762b2325ffSGerd Hoffmann LIBUSB_LOG_LEVEL_WARNING), 17772b2325ffSGerd Hoffmann DEFINE_PROP_BIT("pipeline", USBHostDevice, options, 17782b2325ffSGerd Hoffmann USB_HOST_OPT_PIPELINE, true), 17797bacaf5fSYuri Benditovich DEFINE_PROP_BOOL("suppress-remote-wake", USBHostDevice, 17807bacaf5fSYuri Benditovich suppress_remote_wake, true), 17812b2325ffSGerd Hoffmann DEFINE_PROP_END_OF_LIST(), 17822b2325ffSGerd Hoffmann }; 17832b2325ffSGerd Hoffmann 17842b2325ffSGerd Hoffmann static void usb_host_class_initfn(ObjectClass *klass, void *data) 17852b2325ffSGerd Hoffmann { 17862b2325ffSGerd Hoffmann DeviceClass *dc = DEVICE_CLASS(klass); 17872b2325ffSGerd Hoffmann USBDeviceClass *uc = USB_DEVICE_CLASS(klass); 17882b2325ffSGerd Hoffmann 17892aa76dc1SGonglei uc->realize = usb_host_realize; 17902b2325ffSGerd Hoffmann uc->product_desc = "USB Host Device"; 17912b2325ffSGerd Hoffmann uc->cancel_packet = usb_host_cancel_packet; 17922b2325ffSGerd Hoffmann uc->handle_data = usb_host_handle_data; 17932b2325ffSGerd Hoffmann uc->handle_control = usb_host_handle_control; 17942b2325ffSGerd Hoffmann uc->handle_reset = usb_host_handle_reset; 1795c4fe9700SMarc-André Lureau uc->unrealize = usb_host_unrealize; 17962b2325ffSGerd Hoffmann uc->flush_ep_queue = usb_host_flush_ep_queue; 179756a9f180SHans de Goede uc->alloc_streams = usb_host_alloc_streams; 179856a9f180SHans de Goede uc->free_streams = usb_host_free_streams; 17992b2325ffSGerd Hoffmann dc->vmsd = &vmstate_usb_host; 18004f67d30bSMarc-André Lureau device_class_set_props(dc, usb_host_dev_properties); 1801125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 18022b2325ffSGerd Hoffmann } 18032b2325ffSGerd Hoffmann 18042b2325ffSGerd Hoffmann static TypeInfo usb_host_dev_info = { 18052b2325ffSGerd Hoffmann .name = TYPE_USB_HOST_DEVICE, 18062b2325ffSGerd Hoffmann .parent = TYPE_USB_DEVICE, 18072b2325ffSGerd Hoffmann .instance_size = sizeof(USBHostDevice), 18082b2325ffSGerd Hoffmann .class_init = usb_host_class_initfn, 1809e6adae52SGonglei .instance_init = usb_host_instance_init, 18102b2325ffSGerd Hoffmann }; 1811627302afSGerd Hoffmann module_obj(TYPE_USB_HOST_DEVICE); 18122b2325ffSGerd Hoffmann 18132b2325ffSGerd Hoffmann static void usb_host_register_types(void) 18142b2325ffSGerd Hoffmann { 18152b2325ffSGerd Hoffmann type_register_static(&usb_host_dev_info); 1816f1a74bf9SGerd Hoffmann monitor_register_hmp("usbhost", true, hmp_info_usbhost); 18172b2325ffSGerd Hoffmann } 18182b2325ffSGerd Hoffmann 18192b2325ffSGerd Hoffmann type_init(usb_host_register_types) 18202b2325ffSGerd Hoffmann 18212b2325ffSGerd Hoffmann /* ------------------------------------------------------------------------ */ 18222b2325ffSGerd Hoffmann 18232b2325ffSGerd Hoffmann static QEMUTimer *usb_auto_timer; 18242b2325ffSGerd Hoffmann static VMChangeStateEntry *usb_vmstate; 18252b2325ffSGerd Hoffmann 1826538f0497SPhilippe Mathieu-Daudé static void usb_host_vm_state(void *unused, bool running, RunState state) 18272b2325ffSGerd Hoffmann { 18282b2325ffSGerd Hoffmann if (running) { 18292b2325ffSGerd Hoffmann usb_host_auto_check(unused); 18302b2325ffSGerd Hoffmann } 18312b2325ffSGerd Hoffmann } 18322b2325ffSGerd Hoffmann 18332b2325ffSGerd Hoffmann static void usb_host_auto_check(void *unused) 18342b2325ffSGerd Hoffmann { 18352b2325ffSGerd Hoffmann struct USBHostDevice *s; 18362b2325ffSGerd Hoffmann struct USBAutoFilter *f; 18373ce21445SJincheng Miao libusb_device **devs = NULL; 18382b2325ffSGerd Hoffmann struct libusb_device_descriptor ddesc; 18392b2325ffSGerd Hoffmann int unconnected = 0; 18402b2325ffSGerd Hoffmann int i, n; 18412b2325ffSGerd Hoffmann 18422b2325ffSGerd Hoffmann if (usb_host_init() != 0) { 18432b2325ffSGerd Hoffmann return; 18442b2325ffSGerd Hoffmann } 18452b2325ffSGerd Hoffmann 18462b2325ffSGerd Hoffmann if (runstate_is_running()) { 18472b2325ffSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 18482b2325ffSGerd Hoffmann for (i = 0; i < n; i++) { 18492b2325ffSGerd Hoffmann if (libusb_get_device_descriptor(devs[i], &ddesc) != 0) { 18502b2325ffSGerd Hoffmann continue; 18512b2325ffSGerd Hoffmann } 18522b2325ffSGerd Hoffmann if (ddesc.bDeviceClass == LIBUSB_CLASS_HUB) { 18532b2325ffSGerd Hoffmann continue; 18542b2325ffSGerd Hoffmann } 18552b2325ffSGerd Hoffmann QTAILQ_FOREACH(s, &hostdevs, next) { 18562b2325ffSGerd Hoffmann f = &s->match; 18572b2325ffSGerd Hoffmann if (f->bus_num > 0 && 18582b2325ffSGerd Hoffmann f->bus_num != libusb_get_bus_number(devs[i])) { 18592b2325ffSGerd Hoffmann continue; 18602b2325ffSGerd Hoffmann } 18612b2325ffSGerd Hoffmann if (f->addr > 0 && 18622b2325ffSGerd Hoffmann f->addr != libusb_get_device_address(devs[i])) { 18632b2325ffSGerd Hoffmann continue; 18642b2325ffSGerd Hoffmann } 18652b2325ffSGerd Hoffmann if (f->port != NULL) { 18662b2325ffSGerd Hoffmann char port[16] = "-"; 18672b2325ffSGerd Hoffmann usb_host_get_port(devs[i], port, sizeof(port)); 18682b2325ffSGerd Hoffmann if (strcmp(f->port, port) != 0) { 18692b2325ffSGerd Hoffmann continue; 18702b2325ffSGerd Hoffmann } 18712b2325ffSGerd Hoffmann } 18722b2325ffSGerd Hoffmann if (f->vendor_id > 0 && 18732b2325ffSGerd Hoffmann f->vendor_id != ddesc.idVendor) { 18742b2325ffSGerd Hoffmann continue; 18752b2325ffSGerd Hoffmann } 18762b2325ffSGerd Hoffmann if (f->product_id > 0 && 18772b2325ffSGerd Hoffmann f->product_id != ddesc.idProduct) { 18782b2325ffSGerd Hoffmann continue; 18792b2325ffSGerd Hoffmann } 18802b2325ffSGerd Hoffmann 18812b2325ffSGerd Hoffmann /* We got a match */ 18822b2325ffSGerd Hoffmann s->seen++; 18832b2325ffSGerd Hoffmann if (s->errcount >= 3) { 18842b2325ffSGerd Hoffmann continue; 18852b2325ffSGerd Hoffmann } 18862b2325ffSGerd Hoffmann if (s->dh != NULL) { 18872b2325ffSGerd Hoffmann continue; 18882b2325ffSGerd Hoffmann } 18899f815e83SGerd Hoffmann if (usb_host_open(s, devs[i], 0) < 0) { 18902b2325ffSGerd Hoffmann s->errcount++; 18912b2325ffSGerd Hoffmann continue; 18922b2325ffSGerd Hoffmann } 18932b2325ffSGerd Hoffmann break; 18942b2325ffSGerd Hoffmann } 18952b2325ffSGerd Hoffmann } 18962b2325ffSGerd Hoffmann libusb_free_device_list(devs, 1); 18972b2325ffSGerd Hoffmann 18982b2325ffSGerd Hoffmann QTAILQ_FOREACH(s, &hostdevs, next) { 18992b2325ffSGerd Hoffmann if (s->dh == NULL) { 19002b2325ffSGerd Hoffmann unconnected++; 19012b2325ffSGerd Hoffmann } 19022b2325ffSGerd Hoffmann if (s->seen == 0) { 19032b2325ffSGerd Hoffmann if (s->dh) { 19042b2325ffSGerd Hoffmann usb_host_close(s); 19052b2325ffSGerd Hoffmann } 19062b2325ffSGerd Hoffmann s->errcount = 0; 19072b2325ffSGerd Hoffmann } 19082b2325ffSGerd Hoffmann s->seen = 0; 19092b2325ffSGerd Hoffmann } 19102b2325ffSGerd Hoffmann 19112b2325ffSGerd Hoffmann #if 0 19122b2325ffSGerd Hoffmann if (unconnected == 0) { 19132b2325ffSGerd Hoffmann /* nothing to watch */ 19142b2325ffSGerd Hoffmann if (usb_auto_timer) { 1915bc72ad67SAlex Bligh timer_del(usb_auto_timer); 19162b2325ffSGerd Hoffmann trace_usb_host_auto_scan_disabled(); 19172b2325ffSGerd Hoffmann } 19182b2325ffSGerd Hoffmann return; 19192b2325ffSGerd Hoffmann } 19202b2325ffSGerd Hoffmann #endif 19212b2325ffSGerd Hoffmann } 19222b2325ffSGerd Hoffmann 19232b2325ffSGerd Hoffmann if (!usb_vmstate) { 19242b2325ffSGerd Hoffmann usb_vmstate = qemu_add_vm_change_state_handler(usb_host_vm_state, NULL); 19252b2325ffSGerd Hoffmann } 19262b2325ffSGerd Hoffmann if (!usb_auto_timer) { 1927bc72ad67SAlex Bligh usb_auto_timer = timer_new_ms(QEMU_CLOCK_REALTIME, usb_host_auto_check, NULL); 19282b2325ffSGerd Hoffmann if (!usb_auto_timer) { 19292b2325ffSGerd Hoffmann return; 19302b2325ffSGerd Hoffmann } 19312b2325ffSGerd Hoffmann trace_usb_host_auto_scan_enabled(); 19322b2325ffSGerd Hoffmann } 1933bc72ad67SAlex Bligh timer_mod(usb_auto_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 2000); 19342b2325ffSGerd Hoffmann } 19352b2325ffSGerd Hoffmann 19361ce6be24SMarkus Armbruster void hmp_info_usbhost(Monitor *mon, const QDict *qdict) 19372b2325ffSGerd Hoffmann { 19383ce21445SJincheng Miao libusb_device **devs = NULL; 19392b2325ffSGerd Hoffmann struct libusb_device_descriptor ddesc; 19402b2325ffSGerd Hoffmann char port[16]; 19412b2325ffSGerd Hoffmann int i, n; 19422b2325ffSGerd Hoffmann 19432b2325ffSGerd Hoffmann if (usb_host_init() != 0) { 19442b2325ffSGerd Hoffmann return; 19452b2325ffSGerd Hoffmann } 19462b2325ffSGerd Hoffmann 19472b2325ffSGerd Hoffmann n = libusb_get_device_list(ctx, &devs); 19482b2325ffSGerd Hoffmann for (i = 0; i < n; i++) { 19492b2325ffSGerd Hoffmann if (libusb_get_device_descriptor(devs[i], &ddesc) != 0) { 19502b2325ffSGerd Hoffmann continue; 19512b2325ffSGerd Hoffmann } 19522b2325ffSGerd Hoffmann if (ddesc.bDeviceClass == LIBUSB_CLASS_HUB) { 19532b2325ffSGerd Hoffmann continue; 19542b2325ffSGerd Hoffmann } 19552b2325ffSGerd Hoffmann usb_host_get_port(devs[i], port, sizeof(port)); 19562b2325ffSGerd Hoffmann monitor_printf(mon, " Bus %d, Addr %d, Port %s, Speed %s Mb/s\n", 19572b2325ffSGerd Hoffmann libusb_get_bus_number(devs[i]), 19582b2325ffSGerd Hoffmann libusb_get_device_address(devs[i]), 19592b2325ffSGerd Hoffmann port, 19602b2325ffSGerd Hoffmann speed_name[libusb_get_device_speed(devs[i])]); 19612b2325ffSGerd Hoffmann monitor_printf(mon, " Class %02x:", ddesc.bDeviceClass); 19622b2325ffSGerd Hoffmann monitor_printf(mon, " USB device %04x:%04x", 19632b2325ffSGerd Hoffmann ddesc.idVendor, ddesc.idProduct); 19642b2325ffSGerd Hoffmann if (ddesc.iProduct) { 19652b2325ffSGerd Hoffmann libusb_device_handle *handle; 19662b2325ffSGerd Hoffmann if (libusb_open(devs[i], &handle) == 0) { 19672b2325ffSGerd Hoffmann unsigned char name[64] = ""; 19682b2325ffSGerd Hoffmann libusb_get_string_descriptor_ascii(handle, 19692b2325ffSGerd Hoffmann ddesc.iProduct, 19702b2325ffSGerd Hoffmann name, sizeof(name)); 19712b2325ffSGerd Hoffmann libusb_close(handle); 19722b2325ffSGerd Hoffmann monitor_printf(mon, ", %s", name); 19732b2325ffSGerd Hoffmann } 19742b2325ffSGerd Hoffmann } 19752b2325ffSGerd Hoffmann monitor_printf(mon, "\n"); 19762b2325ffSGerd Hoffmann } 19772b2325ffSGerd Hoffmann libusb_free_device_list(devs, 1); 19782b2325ffSGerd Hoffmann } 1979