提交 2a7a239f 编写于 作者: A Anthony Liguori

Merge remote-tracking branch 'kraxel/usb.79' into staging

# By Gerd Hoffmann (7) and Hans de Goede (3)
# Via Gerd Hoffmann
* kraxel/usb.79:
  usb-tablet: Don't claim wakeup capability for USB-2 version
  usb: update docs for bus name change
  usb-hub: report status changes only once
  usb-hub: limit chain length
  xhci: zap unused name field
  xhci: remove unimplemented printfs
  xhci: remove leftover debug printf
  xhci: fix numintrs sanity checks
  usb-redir: Add flow control support
  usb-redir: Fix crash on migration with no client connected
...@@ -11,7 +11,7 @@ one USB 2.0 bus driven by the EHCI controller. Devices must be ...@@ -11,7 +11,7 @@ one USB 2.0 bus driven by the EHCI controller. Devices must be
attached to the correct controller manually. attached to the correct controller manually.
The '-usb' switch will make qemu create the UHCI controller as part of The '-usb' switch will make qemu create the UHCI controller as part of
the PIIX3 chipset. The USB 1.1 bus will carry the name "usb.0". the PIIX3 chipset. The USB 1.1 bus will carry the name "usb-bus.0".
You can use the standard -device switch to add a EHCI controller to You can use the standard -device switch to add a EHCI controller to
your virtual machine. It is strongly recommended to specify an ID for your virtual machine. It is strongly recommended to specify an ID for
...@@ -27,7 +27,7 @@ a complete example: ...@@ -27,7 +27,7 @@ a complete example:
-drive if=none,id=usbstick,file=/path/to/image \ -drive if=none,id=usbstick,file=/path/to/image \
-usb \ -usb \
-device usb-ehci,id=ehci \ -device usb-ehci,id=ehci \
-device usb-tablet,bus=usb.0 \ -device usb-tablet,bus=usb-bus.0 \
-device usb-storage,bus=ehci.0,drive=usbstick -device usb-storage,bus=ehci.0,drive=usbstick
This attaches a usb tablet to the UHCI adapter and a usb mass storage This attaches a usb tablet to the UHCI adapter and a usb mass storage
...@@ -88,22 +88,22 @@ ports (1-4), the emulated (1.1) USB hub has eight ports. ...@@ -88,22 +88,22 @@ ports (1-4), the emulated (1.1) USB hub has eight ports.
Plugging a tablet into UHCI port 1 works like this: Plugging a tablet into UHCI port 1 works like this:
-device usb-tablet,bus=usb.0,port=1 -device usb-tablet,bus=usb-bus.0,port=1
Plugging a hub into UHCI port 2 works like this: Plugging a hub into UHCI port 2 works like this:
-device usb-hub,bus=usb.0,port=2 -device usb-hub,bus=usb-bus.0,port=2
Plugging a virtual usb stick into port 4 of the hub just plugged works Plugging a virtual usb stick into port 4 of the hub just plugged works
this way: this way:
-device usb-storage,bus=usb.0,port=2.4,drive=... -device usb-storage,bus=usb-bus.0,port=2.4,drive=...
You can do basically the same in the monitor using the device_add You can do basically the same in the monitor using the device_add
command. If you want to unplug devices too you should specify some command. If you want to unplug devices too you should specify some
unique id which you can use to refer to the device ... unique id which you can use to refer to the device ...
(qemu) device_add usb-tablet,bus=usb.0,port=1,id=my-tablet (qemu) device_add usb-tablet,bus=usb-bus.0,port=1,id=my-tablet
(qemu) device_del my-tablet (qemu) device_del my-tablet
... when unplugging it with device_del. ... when unplugging it with device_del.
...@@ -148,10 +148,10 @@ using for testing is bus 1 + port 1 for 2.0 devices and bus 3 + port 1 ...@@ -148,10 +148,10 @@ using for testing is bus 1 + port 1 for 2.0 devices and bus 3 + port 1
for 1.1 devices. Passing through any device plugged into that port for 1.1 devices. Passing through any device plugged into that port
and also assign them to the correct bus can be done this way: and also assign them to the correct bus can be done this way:
qemu -M pc ${otheroptions} \ qemu -M pc ${otheroptions} \
-usb \ -usb \
-device usb-ehci,id=ehci \ -device usb-ehci,id=ehci \
-device usb-host,bus=usb.0,hostbus=3,hostport=1 \ -device usb-host,bus=usb-bus.0,hostbus=3,hostport=1 \
-device usb-host,bus=ehci.0,hostbus=1,hostport=1 -device usb-host,bus=ehci.0,hostbus=1,hostport=1
enjoy, enjoy,
......
...@@ -337,6 +337,7 @@ typedef struct USBPortOps { ...@@ -337,6 +337,7 @@ typedef struct USBPortOps {
struct USBPort { struct USBPort {
USBDevice *dev; USBDevice *dev;
int speedmask; int speedmask;
int hubcount;
char path[16]; char path[16];
USBPortOps *ops; USBPortOps *ops;
void *opaque; void *opaque;
......
...@@ -341,8 +341,10 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr) ...@@ -341,8 +341,10 @@ void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
if (upstream) { if (upstream) {
snprintf(downstream->path, sizeof(downstream->path), "%s.%d", snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
upstream->path, portnr); upstream->path, portnr);
downstream->hubcount = upstream->hubcount + 1;
} else { } else {
snprintf(downstream->path, sizeof(downstream->path), "%d", portnr); snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
downstream->hubcount = 0;
} }
} }
......
...@@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = { ...@@ -236,7 +236,7 @@ static const USBDescDevice desc_device_tablet2 = {
.bNumInterfaces = 1, .bNumInterfaces = 1,
.bConfigurationValue = 1, .bConfigurationValue = 1,
.iConfiguration = STR_CONFIG_TABLET, .iConfiguration = STR_CONFIG_TABLET,
.bmAttributes = 0xa0, .bmAttributes = 0x80,
.bMaxPower = 50, .bMaxPower = 50,
.nif = 1, .nif = 1,
.ifs = &desc_iface_tablet2, .ifs = &desc_iface_tablet2,
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "trace.h" #include "trace.h"
#include "hw/usb.h" #include "hw/usb.h"
#include "hw/usb/desc.h" #include "hw/usb/desc.h"
#include "qemu/error-report.h"
#define NUM_PORTS 8 #define NUM_PORTS 8
...@@ -32,6 +33,7 @@ typedef struct USBHubPort { ...@@ -32,6 +33,7 @@ typedef struct USBHubPort {
USBPort port; USBPort port;
uint16_t wPortStatus; uint16_t wPortStatus;
uint16_t wPortChange; uint16_t wPortChange;
uint16_t wPortChange_reported;
} USBHubPort; } USBHubPort;
typedef struct USBHubState { typedef struct USBHubState {
...@@ -466,8 +468,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p) ...@@ -466,8 +468,11 @@ static void usb_hub_handle_data(USBDevice *dev, USBPacket *p)
status = 0; status = 0;
for(i = 0; i < NUM_PORTS; i++) { for(i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i]; port = &s->ports[i];
if (port->wPortChange) if (port->wPortChange &&
port->wPortChange_reported != port->wPortChange) {
status |= (1 << (i + 1)); status |= (1 << (i + 1));
}
port->wPortChange_reported = port->wPortChange;
} }
if (status != 0) { if (status != 0) {
for(i = 0; i < n; i++) { for(i = 0; i < n; i++) {
...@@ -514,6 +519,11 @@ static int usb_hub_initfn(USBDevice *dev) ...@@ -514,6 +519,11 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port; USBHubPort *port;
int i; int i;
if (dev->port->hubcount == 5) {
error_report("usb hub chain too deep");
return -1;
}
usb_desc_create_serial(dev); usb_desc_create_serial(dev);
usb_desc_init(dev); usb_desc_init(dev);
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
......
...@@ -452,7 +452,6 @@ struct XHCIState { ...@@ -452,7 +452,6 @@ struct XHCIState {
MemoryRegion mem_oper; MemoryRegion mem_oper;
MemoryRegion mem_runtime; MemoryRegion mem_runtime;
MemoryRegion mem_doorbell; MemoryRegion mem_doorbell;
const char *name;
unsigned int devaddr; unsigned int devaddr;
/* properties */ /* properties */
...@@ -1172,8 +1171,6 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx, ...@@ -1172,8 +1171,6 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
uint32_t ctx[5]; uint32_t ctx[5];
uint32_t ctx2[2]; uint32_t ctx2[2];
fprintf(stderr, "%s: epid %d, state %d\n",
__func__, epctx->epid, state);
xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx)); xhci_dma_read_u32s(xhci, epctx->pctx, ctx, sizeof(ctx));
ctx[0] &= ~EP_STATE_MASK; ctx[0] &= ~EP_STATE_MASK;
ctx[0] |= state; ctx[0] |= state;
...@@ -2568,7 +2565,7 @@ static void xhci_process_commands(XHCIState *xhci) ...@@ -2568,7 +2565,7 @@ static void xhci_process_commands(XHCIState *xhci)
} }
break; break;
default: default:
fprintf(stderr, "xhci: unimplemented command %d\n", type); trace_usb_xhci_unimplemented("command", type);
event.ccode = CC_TRB_ERROR; event.ccode = CC_TRB_ERROR;
break; break;
} }
...@@ -2767,7 +2764,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size) ...@@ -2767,7 +2764,7 @@ static uint64_t xhci_cap_read(void *ptr, hwaddr reg, unsigned size)
ret = 0x00000000; /* reserved */ ret = 0x00000000; /* reserved */
break; break;
default: default:
fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", (int)reg); trace_usb_xhci_unimplemented("cap read", reg);
ret = 0; ret = 0;
} }
...@@ -2790,8 +2787,7 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size) ...@@ -2790,8 +2787,7 @@ static uint64_t xhci_port_read(void *ptr, hwaddr reg, unsigned size)
break; break;
case 0x0c: /* reserved */ case 0x0c: /* reserved */
default: default:
fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n", trace_usb_xhci_unimplemented("port read", reg);
port->portnr, (uint32_t)reg);
ret = 0; ret = 0;
} }
...@@ -2831,8 +2827,7 @@ static void xhci_port_write(void *ptr, hwaddr reg, ...@@ -2831,8 +2827,7 @@ static void xhci_port_write(void *ptr, hwaddr reg,
case 0x04: /* PORTPMSC */ case 0x04: /* PORTPMSC */
case 0x08: /* PORTLI */ case 0x08: /* PORTLI */
default: default:
fprintf(stderr, "xhci_port_write (port %d): reg 0x%x unimplemented\n", trace_usb_xhci_unimplemented("port write", reg);
port->portnr, (uint32_t)reg);
} }
} }
...@@ -2870,7 +2865,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size) ...@@ -2870,7 +2865,7 @@ static uint64_t xhci_oper_read(void *ptr, hwaddr reg, unsigned size)
ret = xhci->config; ret = xhci->config;
break; break;
default: default:
fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", (int)reg); trace_usb_xhci_unimplemented("oper read", reg);
ret = 0; ret = 0;
} }
...@@ -2935,7 +2930,7 @@ static void xhci_oper_write(void *ptr, hwaddr reg, ...@@ -2935,7 +2930,7 @@ static void xhci_oper_write(void *ptr, hwaddr reg,
xhci->config = val & 0xff; xhci->config = val & 0xff;
break; break;
default: default:
fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg); trace_usb_xhci_unimplemented("oper write", reg);
} }
} }
...@@ -2951,8 +2946,7 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg, ...@@ -2951,8 +2946,7 @@ static uint64_t xhci_runtime_read(void *ptr, hwaddr reg,
ret = xhci_mfindex_get(xhci) & 0x3fff; ret = xhci_mfindex_get(xhci) & 0x3fff;
break; break;
default: default:
fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", trace_usb_xhci_unimplemented("runtime read", reg);
(int)reg);
break; break;
} }
} else { } else {
...@@ -2996,7 +2990,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, ...@@ -2996,7 +2990,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
trace_usb_xhci_runtime_write(reg, val); trace_usb_xhci_runtime_write(reg, val);
if (reg < 0x20) { if (reg < 0x20) {
fprintf(stderr, "%s: reg 0x%x unimplemented\n", __func__, (int)reg); trace_usb_xhci_unimplemented("runtime write", reg);
return; return;
} }
...@@ -3038,8 +3032,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg, ...@@ -3038,8 +3032,7 @@ static void xhci_runtime_write(void *ptr, hwaddr reg,
xhci_events_update(xhci, v); xhci_events_update(xhci, v);
break; break;
default: default:
fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", trace_usb_xhci_unimplemented("oper write", reg);
(int)reg);
} }
} }
...@@ -3290,6 +3283,9 @@ static int usb_xhci_initfn(struct PCIDevice *dev) ...@@ -3290,6 +3283,9 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
if (xhci->numintrs > MAXINTRS) { if (xhci->numintrs > MAXINTRS) {
xhci->numintrs = MAXINTRS; xhci->numintrs = MAXINTRS;
} }
while (xhci->numintrs & (xhci->numintrs - 1)) { /* ! power of 2 */
xhci->numintrs++;
}
if (xhci->numintrs < 1) { if (xhci->numintrs < 1) {
xhci->numintrs = 1; xhci->numintrs = 1;
} }
......
...@@ -104,6 +104,8 @@ struct USBRedirDevice { ...@@ -104,6 +104,8 @@ struct USBRedirDevice {
/* Data passed from chardev the fd_read cb to the usbredirparser read cb */ /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
const uint8_t *read_buf; const uint8_t *read_buf;
int read_buf_size; int read_buf_size;
/* Active chardev-watch-tag */
guint watch;
/* For async handling of close */ /* For async handling of close */
QEMUBH *chardev_close_bh; QEMUBH *chardev_close_bh;
/* To delay the usb attach in case of quick chardev close + open */ /* To delay the usb attach in case of quick chardev close + open */
...@@ -254,9 +256,21 @@ static int usbredir_read(void *priv, uint8_t *data, int count) ...@@ -254,9 +256,21 @@ static int usbredir_read(void *priv, uint8_t *data, int count)
return count; return count;
} }
static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
void *opaque)
{
USBRedirDevice *dev = opaque;
dev->watch = 0;
usbredirparser_do_write(dev->parser);
return FALSE;
}
static int usbredir_write(void *priv, uint8_t *data, int count) static int usbredir_write(void *priv, uint8_t *data, int count)
{ {
USBRedirDevice *dev = priv; USBRedirDevice *dev = priv;
int r;
if (!dev->cs->be_open) { if (!dev->cs->be_open) {
return 0; return 0;
...@@ -267,7 +281,17 @@ static int usbredir_write(void *priv, uint8_t *data, int count) ...@@ -267,7 +281,17 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
return 0; return 0;
} }
return qemu_chr_fe_write(dev->cs, data, count); r = qemu_chr_fe_write(dev->cs, data, count);
if (r < count) {
if (!dev->watch) {
dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT,
usbredir_write_unblocked, dev);
}
if (r < 0) {
r = 0;
}
}
return r;
} }
/* /*
...@@ -1085,6 +1109,10 @@ static void usbredir_chardev_close_bh(void *opaque) ...@@ -1085,6 +1109,10 @@ static void usbredir_chardev_close_bh(void *opaque)
usbredirparser_destroy(dev->parser); usbredirparser_destroy(dev->parser);
dev->parser = NULL; dev->parser = NULL;
} }
if (dev->watch) {
g_source_remove(dev->watch);
dev->watch = 0;
}
} }
static void usbredir_create_parser(USBRedirDevice *dev) static void usbredir_create_parser(USBRedirDevice *dev)
...@@ -1317,6 +1345,9 @@ static void usbredir_handle_destroy(USBDevice *udev) ...@@ -1317,6 +1345,9 @@ static void usbredir_handle_destroy(USBDevice *udev)
if (dev->parser) { if (dev->parser) {
usbredirparser_destroy(dev->parser); usbredirparser_destroy(dev->parser);
} }
if (dev->watch) {
g_source_remove(dev->watch);
}
free(dev->filter_rules); free(dev->filter_rules);
} }
...@@ -1973,6 +2004,10 @@ static int usbredir_post_load(void *priv, int version_id) ...@@ -1973,6 +2004,10 @@ static int usbredir_post_load(void *priv, int version_id)
{ {
USBRedirDevice *dev = priv; USBRedirDevice *dev = priv;
if (dev->parser == NULL) {
return 0;
}
switch (dev->device_info.speed) { switch (dev->device_info.speed) {
case usb_redir_speed_low: case usb_redir_speed_low:
dev->dev.speed = USB_SPEED_LOW; dev->dev.speed = USB_SPEED_LOW;
......
...@@ -380,6 +380,7 @@ usb_xhci_xfer_nak(void *xfer) "%p" ...@@ -380,6 +380,7 @@ usb_xhci_xfer_nak(void *xfer) "%p"
usb_xhci_xfer_retry(void *xfer) "%p" usb_xhci_xfer_retry(void *xfer) "%p"
usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d" usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d" usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
# hw/usb/desc.c # hw/usb/desc.c
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d" usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册