Add support for (re-)initializing endpoints which belong to a specific interface only. Use this in usb-host when changing altsetting for an interface, so other interfaces are not disturbed.
Signed-off-by: Gerd Hoffmann <kra...@redhat.com> --- hw/usb.h | 2 +- hw/usb/bus.c | 2 +- hw/usb/core.c | 48 +++++++++++++++++++++++++++--------------------- hw/usb/desc.c | 2 +- hw/usb/host-linux.c | 16 ++++++++-------- hw/usb/redirect.c | 2 +- 6 files changed, 39 insertions(+), 33 deletions(-) diff --git a/hw/usb.h b/hw/usb.h index a5623d3..b6d7052 100644 --- a/hw/usb.h +++ b/hw/usb.h @@ -362,7 +362,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p); void usb_packet_complete(USBDevice *dev, USBPacket *p); void usb_cancel_packet(USBPacket * p); -void usb_ep_init(USBDevice *dev); +void usb_ep_init(USBDevice *dev, int interface); void usb_ep_dump(USBDevice *dev); struct USBEndpoint *usb_ep_get(USBDevice *dev, int pid, int ep); uint8_t usb_ep_get_type(USBDevice *dev, int pid, int ep); diff --git a/hw/usb/bus.c b/hw/usb/bus.c index b649360..ad1daaf 100644 --- a/hw/usb/bus.c +++ b/hw/usb/bus.c @@ -190,7 +190,7 @@ static int usb_qdev_init(DeviceState *qdev) usb_device_get_product_desc(dev)); dev->auto_attach = 1; QLIST_INIT(&dev->strings); - usb_ep_init(dev); + usb_ep_init(dev, 0); rc = usb_claim_port(dev); if (rc != 0) { return rc; diff --git a/hw/usb/core.c b/hw/usb/core.c index 0e02da7..94c3c1a 100644 --- a/hw/usb/core.c +++ b/hw/usb/core.c @@ -550,31 +550,37 @@ void usb_packet_cleanup(USBPacket *p) qemu_iovec_destroy(&p->iov); } -void usb_ep_init(USBDevice *dev) +void usb_ep_init(USBDevice *dev, int interface) { int ep; - dev->ep_ctl.nr = 0; - dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL; - dev->ep_ctl.ifnum = 0; - dev->ep_ctl.dev = dev; - dev->ep_ctl.pipeline = false; - QTAILQ_INIT(&dev->ep_ctl.queue); + if (interface == 0) { + dev->ep_ctl.nr = 0; + dev->ep_ctl.type = USB_ENDPOINT_XFER_CONTROL; + dev->ep_ctl.ifnum = 0; + dev->ep_ctl.dev = dev; + dev->ep_ctl.pipeline = false; + QTAILQ_INIT(&dev->ep_ctl.queue); + } for (ep = 0; ep < USB_MAX_ENDPOINTS; ep++) { - dev->ep_in[ep].nr = ep + 1; - dev->ep_out[ep].nr = ep + 1; - dev->ep_in[ep].pid = USB_TOKEN_IN; - dev->ep_out[ep].pid = USB_TOKEN_OUT; - dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; - dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; - dev->ep_in[ep].ifnum = 0; - dev->ep_out[ep].ifnum = 0; - dev->ep_in[ep].dev = dev; - dev->ep_out[ep].dev = dev; - dev->ep_in[ep].pipeline = false; - dev->ep_out[ep].pipeline = false; - QTAILQ_INIT(&dev->ep_in[ep].queue); - QTAILQ_INIT(&dev->ep_out[ep].queue); + if (interface == 0 || interface == dev->ep_in[ep].ifnum) { + dev->ep_in[ep].nr = ep + 1; + dev->ep_in[ep].pid = USB_TOKEN_IN; + dev->ep_in[ep].type = USB_ENDPOINT_XFER_INVALID; + dev->ep_in[ep].ifnum = 0; + dev->ep_in[ep].dev = dev; + dev->ep_in[ep].pipeline = false; + QTAILQ_INIT(&dev->ep_in[ep].queue); + } + if (interface == 0 || interface == dev->ep_out[ep].ifnum) { + dev->ep_out[ep].nr = ep + 1; + dev->ep_out[ep].pid = USB_TOKEN_OUT; + dev->ep_out[ep].type = USB_ENDPOINT_XFER_INVALID; + dev->ep_out[ep].ifnum = 0; + dev->ep_out[ep].dev = dev; + dev->ep_out[ep].pipeline = false; + QTAILQ_INIT(&dev->ep_out[ep].queue); + } } } diff --git a/hw/usb/desc.c b/hw/usb/desc.c index 0a9d3c9..f010755 100644 --- a/hw/usb/desc.c +++ b/hw/usb/desc.c @@ -246,7 +246,7 @@ static void usb_desc_ep_init(USBDevice *dev) const USBDescIface *iface; int i, e, pid, ep; - usb_ep_init(dev); + usb_ep_init(dev, 0); for (i = 0; i < dev->ninterfaces; i++) { iface = dev->ifaces[i]; if (iface == NULL) { diff --git a/hw/usb/host-linux.c b/hw/usb/host-linux.c index 5479fb5..8e5d1be 100644 --- a/hw/usb/host-linux.c +++ b/hw/usb/host-linux.c @@ -135,7 +135,7 @@ static int parse_filter(const char *spec, struct USBAutoFilter *f); static void usb_host_auto_check(void *unused); static int usb_host_read_file(char *line, size_t line_size, const char *device_file, const char *device_name); -static int usb_linux_update_endp_table(USBHostDevice *s); +static int usb_linux_update_endp_table(USBHostDevice *s, int ifnum); static int usb_host_usbfs_type(USBHostDevice *s, USBPacket *p) { @@ -648,7 +648,7 @@ static void usb_host_handle_reset(USBDevice *dev) usb_host_do_reset(s);; usb_host_claim_interfaces(s, 0); - usb_linux_update_endp_table(s); + usb_linux_update_endp_table(s, 0); } static void usb_host_handle_destroy(USBDevice *dev) @@ -988,7 +988,7 @@ again: return ctrl_error(); } usb_host_claim_interfaces(s, config); - usb_linux_update_endp_table(s); + usb_linux_update_endp_table(s, 0); return 0; } @@ -1024,7 +1024,7 @@ static int usb_host_set_interface(USBHostDevice *s, int iface, int alt) } s->dev.altsetting[iface] = alt; - usb_linux_update_endp_table(s); + usb_linux_update_endp_table(s, iface); return 0; } @@ -1120,7 +1120,7 @@ static int usb_host_handle_control(USBDevice *dev, USBPacket *p, } /* returns 1 on problem encountered or 0 for success */ -static int usb_linux_update_endp_table(USBHostDevice *s) +static int usb_linux_update_endp_table(USBHostDevice *s, int ifnum) { static const char *tname[] = { [USB_ENDPOINT_XFER_CONTROL] = "control", @@ -1136,7 +1136,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s) USBDescriptor *d; bool active = false; - usb_ep_init(&s->dev); + usb_ep_init(&s->dev, ifnum); for (i = 0;; i += d->bLength) { if (i+2 >= s->descr_len) { @@ -1239,7 +1239,7 @@ static int usb_linux_update_endp_table(USBHostDevice *s) return 0; error: - usb_ep_init(&s->dev); + usb_ep_init(&s->dev, 0); return 1; } @@ -1326,7 +1326,7 @@ static int usb_host_open(USBHostDevice *dev, int bus_num, goto fail; } - ret = usb_linux_update_endp_table(dev); + ret = usb_linux_update_endp_table(dev, 0); if (ret) { goto fail; } diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index d949f04..4afa9c2 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -1136,7 +1136,7 @@ static void usbredir_device_disconnect(void *priv) for (i = 0; i < MAX_ENDPOINTS; i++) { QTAILQ_INIT(&dev->endpoint[i].bufpq); } - usb_ep_init(&dev->dev); + usb_ep_init(&dev->dev, 0); dev->interface_info.interface_count = NO_INTERFACE_INFO; dev->dev.addr = 0; dev->dev.speed = 0; -- 1.7.1