mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 13:30:52 +00:00
usb: bugfixes for xhci, usb pass-through and usb redirection.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJeHGtbAAoJEEy22O7T6HE43vQQANtKv7pd2FsvgXsXc8nK1VOP oiGQdL96pUCHHQvPWOE9z+PhmwCoyJ3NSE2p1iDkiIHqyNykZSvlO9FADwPeKnUu b5oJpj1Joewrzdb7N8/Fs0TVq6/4KFiTXUGf1mdAi1TIrFDGOCtLllQMOj2nlMuV kfCKd8hbv41OSy4buDZb7BA4sKREynfZneKvFwx/0Er1Xv1wjIPIHgnZiDSqEQf4 /uXGBdYIdMPTaHAK0NJfM1OjIMmjLnd30w4MhjhJRUeRScQhD0+DOZiSmV1mJb6P ddLVystut5+wPPH8cadKqCW6xxwkwaxYe8Mz97j0dyHG4dt9n4iwOb+BjNxRRG/S kLK5TlStnRk8PyzH0qhHKH2YtTpHVfULEM7FRS2MQ6fSLrC8RaW6i9WzfLF+ye42 F7G6AYjU5Re5pFO2kqhcvE/UEFV0Al+AWjRzQDDq0bnRflGz4PCZgckOBfE6OjNp eUpMbfCAeaWcatIIIZYGbl1HXDAdgig4REpJCoM8HgHZV2Fc2e8p/BeXm60t2XV8 YNjfg1gyUSfL1gEYZno+L8ixO5tv4Y+RXRTjt8Hx6zQkNEbEW4nJf7A31SiN2/b3 1l9rPPsn43q3KIOC3Ylg57tSDUQnTBRrCThy1/wYrp9Av8hqb7dNrjFvkoLHRY5x R9cU7rsvnPRqwWbZVUOl =zECN -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/usb-20200113-pull-request' into staging usb: bugfixes for xhci, usb pass-through and usb redirection. # gpg: Signature made Mon 13 Jan 2020 13:06:35 GMT # gpg: using RSA key 4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/usb-20200113-pull-request: xhci: recheck slot status xhci: Fix memory leak in xhci_kick_epctx when poweroff GuestOS usbredir: Prevent recursion in usbredir_write usb-redir: remove 'remote wakeup' flag from configuration descriptor usb-host: remove 'remote wakeup' flag from configuration descriptor Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3c8a657598
@ -32,6 +32,8 @@ GlobalProperty hw_compat_4_2[] = {
|
||||
{ "virtio-blk-device", "seg-max-adjust", "off"},
|
||||
{ "virtio-scsi-device", "seg_max_adjust", "off"},
|
||||
{ "vhost-blk-device", "seg_max_adjust", "off"},
|
||||
{ "usb-host", "suppress-remote-wake", "off" },
|
||||
{ "usb-redir", "suppress-remote-wake", "off" },
|
||||
};
|
||||
const size_t hw_compat_4_2_len = G_N_ELEMENTS(hw_compat_4_2);
|
||||
|
||||
|
@ -1861,6 +1861,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
|
||||
xhci_kick_epctx(epctx, streamid);
|
||||
}
|
||||
|
||||
static bool xhci_slot_ok(XHCIState *xhci, int slotid)
|
||||
{
|
||||
return (xhci->slots[slotid - 1].uport &&
|
||||
xhci->slots[slotid - 1].uport->dev &&
|
||||
xhci->slots[slotid - 1].uport->dev->attached);
|
||||
}
|
||||
|
||||
static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
{
|
||||
XHCIState *xhci = epctx->xhci;
|
||||
@ -1878,9 +1885,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
|
||||
/* If the device has been detached, but the guest has not noticed this
|
||||
yet the 2 above checks will succeed, but we must NOT continue */
|
||||
if (!xhci->slots[epctx->slotid - 1].uport ||
|
||||
!xhci->slots[epctx->slotid - 1].uport->dev ||
|
||||
!xhci->slots[epctx->slotid - 1].uport->dev->attached) {
|
||||
if (!xhci_slot_ok(xhci, epctx->slotid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1987,6 +1992,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
} else {
|
||||
xhci_fire_transfer(xhci, xfer, epctx);
|
||||
}
|
||||
if (!xhci_slot_ok(xhci, epctx->slotid)) {
|
||||
/* surprise removal -> stop processing */
|
||||
break;
|
||||
}
|
||||
if (xfer->complete) {
|
||||
/* update ring dequeue ptr */
|
||||
xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
|
||||
@ -2000,6 +2009,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
|
||||
if (xfer != NULL && xfer->running_retry) {
|
||||
DPRINTF("xhci: xfer nacked, stopping schedule\n");
|
||||
epctx->retry = xfer;
|
||||
xhci_xfer_unmap(xfer);
|
||||
break;
|
||||
}
|
||||
if (count++ > TRANSFER_LIMIT) {
|
||||
|
@ -88,6 +88,7 @@ struct USBHostDevice {
|
||||
bool needs_autoscan;
|
||||
bool allow_one_guest_reset;
|
||||
bool allow_all_guest_resets;
|
||||
bool suppress_remote_wake;
|
||||
|
||||
/* state */
|
||||
QTAILQ_ENTRY(USBHostDevice) next;
|
||||
@ -386,6 +387,8 @@ static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
|
||||
r->p->status = status_map[xfer->status];
|
||||
r->p->actual_length = xfer->actual_length;
|
||||
if (r->in && xfer->actual_length) {
|
||||
USBDevice *udev = USB_DEVICE(s);
|
||||
struct libusb_config_descriptor *conf = (void *)r->cbuf;
|
||||
memcpy(r->cbuf, r->buffer + 8, xfer->actual_length);
|
||||
|
||||
/* Fix up USB-3 ep0 maxpacket size to allow superspeed connected devices
|
||||
@ -394,6 +397,21 @@ static void LIBUSB_CALL usb_host_req_complete_ctrl(struct libusb_transfer *xfer)
|
||||
r->cbuf[7] == 9) {
|
||||
r->cbuf[7] = 64;
|
||||
}
|
||||
/*
|
||||
*If this is GET_DESCRIPTOR request for configuration descriptor,
|
||||
* remove 'remote wakeup' flag from it to prevent idle power down
|
||||
* in Windows guest
|
||||
*/
|
||||
if (s->suppress_remote_wake &&
|
||||
udev->setup_buf[0] == USB_DIR_IN &&
|
||||
udev->setup_buf[1] == USB_REQ_GET_DESCRIPTOR &&
|
||||
udev->setup_buf[3] == USB_DT_CONFIG && udev->setup_buf[2] == 0 &&
|
||||
xfer->actual_length >
|
||||
offsetof(struct libusb_config_descriptor, bmAttributes) &&
|
||||
(conf->bmAttributes & USB_CFG_ATT_WAKEUP)) {
|
||||
trace_usb_host_remote_wakeup_removed(s->bus_num, s->addr);
|
||||
conf->bmAttributes &= ~USB_CFG_ATT_WAKEUP;
|
||||
}
|
||||
}
|
||||
trace_usb_host_req_complete(s->bus_num, s->addr, r->p,
|
||||
r->p->status, r->p->actual_length);
|
||||
@ -1596,6 +1614,8 @@ static Property usb_host_dev_properties[] = {
|
||||
LIBUSB_LOG_LEVEL_WARNING),
|
||||
DEFINE_PROP_BIT("pipeline", USBHostDevice, options,
|
||||
USB_HOST_OPT_PIPELINE, true),
|
||||
DEFINE_PROP_BOOL("suppress-remote-wake", USBHostDevice,
|
||||
suppress_remote_wake, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -113,6 +113,8 @@ struct USBRedirDevice {
|
||||
/* Properties */
|
||||
CharBackend cs;
|
||||
bool enable_streams;
|
||||
bool suppress_remote_wake;
|
||||
bool in_write;
|
||||
uint8_t debug;
|
||||
int32_t bootindex;
|
||||
char *filter_str;
|
||||
@ -290,6 +292,13 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Recursion check */
|
||||
if (dev->in_write) {
|
||||
DPRINTF("usbredir_write recursion\n");
|
||||
return 0;
|
||||
}
|
||||
dev->in_write = true;
|
||||
|
||||
r = qemu_chr_fe_write(&dev->cs, data, count);
|
||||
if (r < count) {
|
||||
if (!dev->watch) {
|
||||
@ -300,6 +309,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
|
||||
r = 0;
|
||||
}
|
||||
}
|
||||
dev->in_write = false;
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1994,6 +2004,23 @@ static void usbredir_control_packet(void *priv, uint64_t id,
|
||||
memcpy(dev->dev.data_buf, data, data_len);
|
||||
}
|
||||
p->actual_length = len;
|
||||
/*
|
||||
* If this is GET_DESCRIPTOR request for configuration descriptor,
|
||||
* remove 'remote wakeup' flag from it to prevent idle power down
|
||||
* in Windows guest
|
||||
*/
|
||||
if (dev->suppress_remote_wake &&
|
||||
control_packet->requesttype == USB_DIR_IN &&
|
||||
control_packet->request == USB_REQ_GET_DESCRIPTOR &&
|
||||
control_packet->value == (USB_DT_CONFIG << 8) &&
|
||||
control_packet->index == 0 &&
|
||||
/* bmAttributes field of config descriptor */
|
||||
len > 7 && (dev->dev.data_buf[7] & USB_CFG_ATT_WAKEUP)) {
|
||||
DPRINTF("Removed remote wake %04X:%04X\n",
|
||||
dev->device_info.vendor_id,
|
||||
dev->device_info.product_id);
|
||||
dev->dev.data_buf[7] &= ~USB_CFG_ATT_WAKEUP;
|
||||
}
|
||||
usb_generic_async_ctrl_complete(&dev->dev, p);
|
||||
}
|
||||
free(data);
|
||||
@ -2535,6 +2562,8 @@ static Property usbredir_properties[] = {
|
||||
DEFINE_PROP_UINT8("debug", USBRedirDevice, debug, usbredirparser_warning),
|
||||
DEFINE_PROP_STRING("filter", USBRedirDevice, filter_str),
|
||||
DEFINE_PROP_BOOL("streams", USBRedirDevice, enable_streams, true),
|
||||
DEFINE_PROP_BOOL("suppress-remote-wake", USBRedirDevice,
|
||||
suppress_remote_wake, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -266,3 +266,4 @@ usb_host_parse_config(int bus, int addr, int value, int active) "dev %d:%d, valu
|
||||
usb_host_parse_interface(int bus, int addr, int num, int alt, int active) "dev %d:%d, num %d, alt %d, active %d"
|
||||
usb_host_parse_endpoint(int bus, int addr, int ep, const char *dir, const char *type, int active) "dev %d:%d, ep %d, %s, %s, active %d"
|
||||
usb_host_parse_error(int bus, int addr, const char *errmsg) "dev %d:%d, msg %s"
|
||||
usb_host_remote_wakeup_removed(int bus, int addr) "dev %d:%d"
|
||||
|
Loading…
Reference in New Issue
Block a user