Compare commits

..

3 Commits

Author SHA1 Message Date
Anthony PERARD
042ec47e68 xen-usb: Fix 32bit build
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Juergen Gross <jgross@suse.com>
Message-id: 20160623110829.22671-1-anthony.perard@citrix.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-07-12 10:47:03 +02:00
Gerd Hoffmann
b91e013982 usb: add storage hotplug documentation
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Message-id: 1466667901-1341-1-git-send-email-kraxel@redhat.com
2016-07-12 10:25:30 +02:00
Zhang Shuaiyi
a4055d8586 nec-usb-xhci: set the device state to USB_STATE_DEFAULT
This patch is a rough fix to "hw/usb/core.c:401: usb_handle_packet:
 Assertion `dev->state == 3' failed.". Qemu will crash when a usb3
device redirect to Windows7 VM via nec-usb-xhci.

In extensible-host-controler-interface-usb-xhci.pdf P94(4.6.5
Address Device):
    • If the Block Set Address Request (BSR) flag = ‘1’
        • If the slot is in the Enabled state:
            ...
            • Set the Slot State in the Output Slot Context to Default.

BSR = ‘1’: Enabled state to Default state; BSR = ‘0’: Default state
to Addressed state. Try to call usb_device_reset to set device state
to USB_STATE_DEFAULT in xhci_address_slot wether bsr is zero.

Signed-off-by: Zhang Shuaiyi <zhang_syi@massclouds.com>
Message-id: 1467258640-11921-1-git-send-email-zhang_syi@massclouds.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2016-07-12 10:23:59 +02:00
8 changed files with 180 additions and 275 deletions

View File

@@ -25,51 +25,16 @@
#include "qemu-common.h"
#include "sysemu/char.h"
#include "ui/console.h"
#include "ui/input.h"
#define MSMOUSE_LO6(n) ((n) & 0x3f)
#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
typedef struct {
CharDriverState *chr;
QemuInputHandlerState *hs;
int axis[INPUT_AXIS__MAX];
bool btns[INPUT_BUTTON__MAX];
bool btnc[INPUT_BUTTON__MAX];
uint8_t outbuf[32];
int outlen;
} MouseState;
static void msmouse_chr_accept_input(CharDriverState *chr)
static void msmouse_event(void *opaque,
int dx, int dy, int dz, int buttons_state)
{
MouseState *mouse = chr->opaque;
int len;
CharDriverState *chr = (CharDriverState *)opaque;
len = qemu_chr_be_can_write(chr);
if (len > mouse->outlen) {
len = mouse->outlen;
}
if (!len) {
return;
}
qemu_chr_be_write(chr, mouse->outbuf, len);
mouse->outlen -= len;
if (mouse->outlen) {
memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen);
}
}
static void msmouse_queue_event(MouseState *mouse)
{
unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
int dx, dy, count = 3;
dx = mouse->axis[INPUT_AXIS_X];
mouse->axis[INPUT_AXIS_X] = 0;
dy = mouse->axis[INPUT_AXIS_Y];
mouse->axis[INPUT_AXIS_Y] = 0;
/* Movement deltas */
bytes[0] |= (MSMOUSE_HI2(dy) << 2) | MSMOUSE_HI2(dx);
@@ -77,54 +42,14 @@ static void msmouse_queue_event(MouseState *mouse)
bytes[2] |= MSMOUSE_LO6(dy);
/* Buttons */
bytes[0] |= (mouse->btns[INPUT_BUTTON_LEFT] ? 0x20 : 0x00);
bytes[0] |= (mouse->btns[INPUT_BUTTON_RIGHT] ? 0x10 : 0x00);
if (mouse->btns[INPUT_BUTTON_MIDDLE] ||
mouse->btnc[INPUT_BUTTON_MIDDLE]) {
bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00);
mouse->btnc[INPUT_BUTTON_MIDDLE] = false;
count = 4;
}
bytes[0] |= (buttons_state & 0x01 ? 0x20 : 0x00);
bytes[0] |= (buttons_state & 0x02 ? 0x10 : 0x00);
bytes[3] |= (buttons_state & 0x04 ? 0x20 : 0x00);
if (mouse->outlen <= sizeof(mouse->outbuf) - count) {
memcpy(mouse->outbuf + mouse->outlen, bytes, count);
mouse->outlen += count;
} else {
/* queue full -> drop event */
}
}
static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
InputEvent *evt)
{
MouseState *mouse = (MouseState *)dev;
InputMoveEvent *move;
InputBtnEvent *btn;
switch (evt->type) {
case INPUT_EVENT_KIND_REL:
move = evt->u.rel.data;
mouse->axis[move->axis] += move->value;
break;
case INPUT_EVENT_KIND_BTN:
btn = evt->u.btn.data;
mouse->btns[btn->button] = btn->down;
mouse->btnc[btn->button] = true;
break;
default:
/* keep gcc happy */
break;
}
}
static void msmouse_input_sync(DeviceState *dev)
{
MouseState *mouse = (MouseState *)dev;
msmouse_queue_event(mouse);
msmouse_chr_accept_input(mouse->chr);
/* We always send the packet of, so that we do not have to keep track
of previous state of the middle button. This can potentially confuse
some very old drivers for two button mice though. */
qemu_chr_be_write(chr, bytes, 4);
}
static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
@@ -135,41 +60,26 @@ static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int
static void msmouse_chr_close (struct CharDriverState *chr)
{
MouseState *mouse = chr->opaque;
qemu_input_handler_unregister(mouse->hs);
g_free(mouse);
g_free(chr);
g_free (chr);
}
static QemuInputHandler msmouse_handler = {
.name = "QEMU Microsoft Mouse",
.mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL,
.event = msmouse_input_event,
.sync = msmouse_input_sync,
};
static CharDriverState *qemu_chr_open_msmouse(const char *id,
ChardevBackend *backend,
ChardevReturn *ret,
Error **errp)
{
ChardevCommon *common = backend->u.msmouse.data;
MouseState *mouse;
CharDriverState *chr;
chr = qemu_chr_alloc(common, errp);
if (!chr) {
return NULL;
}
chr->chr_write = msmouse_chr_write;
chr->chr_close = msmouse_chr_close;
chr->chr_accept_input = msmouse_chr_accept_input;
chr->explicit_be_open = true;
mouse = g_new0(MouseState, 1);
mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
&msmouse_handler);
mouse->chr = chr;
chr->opaque = mouse;
qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
return chr;
}

View File

@@ -40,6 +40,18 @@ numbers must be continuous, i.e. for three devices you must use 0+1+2.
The 0+1+5 numbering from the "usb-uas" example isn't going to work
with "usb-bot".
Starting with qemu version 2.7 usb-bot and usb-uas devices can be
hotplugged. In the hotplug case they are added with "attached =
false" so the guest will not see the device until the "attached"
property is explicitly set to true. That allows to attach one or more
scsi devices before making the device visible to the guest, i.e. the
workflow looks like this:
(1) device-add usb-bot,id=foo
(2) device-add scsi-{hd,cd},bus=foo.0,lun=0
(2b) optionally add more devices (luns 1 ... 15).
(3) scripts/qmp/qom-set foo.attached = true
enjoy,
Gerd

View File

@@ -27,7 +27,6 @@
#include "ui/console.h"
#include "qemu/timer.h"
#include "hw/input/hid.h"
#include "trace.h"
#define HID_USAGE_ERROR_ROLLOVER 0x01
#define HID_USAGE_POSTFAIL 0x02
@@ -235,7 +234,7 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
key->down,
scancodes);
if (hs->n + count > QUEUE_LENGTH) {
trace_hid_kbd_queue_full();
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
for (i = 0; i < count; i++) {

View File

@@ -23,9 +23,3 @@ milkymist_softusb_memory_write(uint32_t addr, uint32_t value) "addr %08x value %
milkymist_softusb_mevt(uint8_t m) "m %d"
milkymist_softusb_kevt(uint8_t m) "m %d"
milkymist_softusb_pulse_irq(void) "Pulse IRQ"
# hw/input/hid.c
hid_kbd_queue_full(void) "queue full"
# hw/input/virtio
virtio_input_queue_full(void) "queue full"

View File

@@ -7,7 +7,6 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/iov.h"
#include "trace.h"
#include "hw/qdev.h"
#include "hw/virtio/virtio.h"
@@ -48,7 +47,7 @@ void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
if (have < need) {
vinput->qindex = 0;
trace_virtio_input_queue_full();
fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__);
return;
}

View File

@@ -2364,6 +2364,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
slot->uport = uport;
slot->ctx = octx;
/* Make sure device is in USB_STATE_DEFAULT state */
usb_device_reset(dev);
if (bsr) {
slot_ctx[3] = SLOT_DEFAULT << SLOT_STATE_SHIFT;
} else {
@@ -2371,7 +2373,6 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
uint8_t buf[1];
slot_ctx[3] = (SLOT_ADDRESSED << SLOT_STATE_SHIFT) | slotid;
usb_device_reset(dev);
memset(&p, 0, sizeof(p));
usb_packet_addbuf(&p, buf, sizeof(buf));
usb_packet_setup(&p, USB_TOKEN_OUT,

View File

@@ -253,7 +253,8 @@ static int usbback_init_packet(struct usbback_req *usbback_req)
case USBIF_PIPE_TYPE_CTRL:
packet->parameter = *(uint64_t *)usbback_req->req.u.ctrl;
TR_REQ(xendev, "ctrl parameter: %lx, buflen: %x\n", packet->parameter,
TR_REQ(xendev, "ctrl parameter: %"PRIx64", buflen: %x\n",
packet->parameter,
usbback_req->req.buffer_length);
break;

View File

@@ -129,17 +129,6 @@ static int qemu_input_linux_to_qcode(unsigned int lnx)
return linux_to_qcode[lnx];
}
static bool linux_is_button(unsigned int lnx)
{
if (lnx < 0x100) {
return false;
}
if (lnx >= 0x160 && lnx < 0x2c0) {
return false;
}
return true;
}
#define TYPE_INPUT_LINUX "input-linux"
#define INPUT_LINUX(obj) \
OBJECT_CHECK(InputLinux, (obj), TYPE_INPUT_LINUX)
@@ -164,12 +153,6 @@ struct InputLinux {
int keycount;
int wheel;
bool initialized;
bool has_rel_x;
bool has_abs_x;
int num_keys;
int num_btns;
QTAILQ_ENTRY(InputLinux) next;
};
@@ -205,39 +188,53 @@ static void input_linux_toggle_grab(InputLinux *il)
}
}
static void input_linux_handle_keyboard(InputLinux *il,
struct input_event *event)
static void input_linux_event_keyboard(void *opaque)
{
if (event->type == EV_KEY) {
if (event->value > 2 || (event->value > 1 && !il->repeat)) {
InputLinux *il = opaque;
struct input_event event;
int rc;
for (;;) {
rc = read(il->fd, &event, sizeof(event));
if (rc != sizeof(event)) {
if (rc < 0 && errno != EAGAIN) {
fprintf(stderr, "%s: read: %s\n", __func__, strerror(errno));
qemu_set_fd_handler(il->fd, NULL, NULL, NULL);
close(il->fd);
}
break;
}
switch (event.type) {
case EV_KEY:
if (event.value > 2 || (event.value > 1 && !il->repeat)) {
/*
* ignore autorepeat + unknown key events
* 0 == up, 1 == down, 2 == autorepeat, other == undefined
*/
return;
continue;
}
if (event->code >= KEY_CNT) {
if (event.code >= KEY_CNT) {
/*
* Should not happen. But better safe than sorry,
* and we make Coverity happy too.
*/
return;
continue;
}
/* keep track of key state */
if (!il->keydown[event->code] && event->value) {
il->keydown[event->code] = true;
if (!il->keydown[event.code] && event.value) {
il->keydown[event.code] = true;
il->keycount++;
}
if (il->keydown[event->code] && !event->value) {
il->keydown[event->code] = false;
if (il->keydown[event.code] && !event.value) {
il->keydown[event.code] = false;
il->keycount--;
}
/* send event to guest when grab is active */
if (il->grab_active) {
int qcode = qemu_input_linux_to_qcode(event->code);
qemu_input_event_send_key_qcode(NULL, qcode, event->value);
int qcode = qemu_input_linux_to_qcode(event.code);
qemu_input_event_send_key_qcode(NULL, qcode, event.value);
}
/* hotkey -> record switch request ... */
@@ -255,6 +252,8 @@ static void input_linux_handle_keyboard(InputLinux *il,
il->grab_request = false;
input_linux_toggle_grab(il);
}
break;
}
}
}
@@ -266,59 +265,7 @@ static void input_linux_event_mouse_button(int button)
qemu_input_event_sync();
}
static void input_linux_handle_mouse(InputLinux *il, struct input_event *event)
{
if (!il->grab_active) {
return;
}
switch (event->type) {
case EV_KEY:
switch (event->code) {
case BTN_LEFT:
qemu_input_queue_btn(NULL, INPUT_BUTTON_LEFT, event->value);
break;
case BTN_RIGHT:
qemu_input_queue_btn(NULL, INPUT_BUTTON_RIGHT, event->value);
break;
case BTN_MIDDLE:
qemu_input_queue_btn(NULL, INPUT_BUTTON_MIDDLE, event->value);
break;
case BTN_GEAR_UP:
qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_UP, event->value);
break;
case BTN_GEAR_DOWN:
qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_DOWN,
event->value);
break;
};
break;
case EV_REL:
switch (event->code) {
case REL_X:
qemu_input_queue_rel(NULL, INPUT_AXIS_X, event->value);
break;
case REL_Y:
qemu_input_queue_rel(NULL, INPUT_AXIS_Y, event->value);
break;
case REL_WHEEL:
il->wheel = event->value;
break;
}
break;
case EV_SYN:
qemu_input_event_sync();
if (il->wheel != 0) {
input_linux_event_mouse_button((il->wheel > 0)
? INPUT_BUTTON_WHEEL_UP
: INPUT_BUTTON_WHEEL_DOWN);
il->wheel = 0;
}
break;
}
}
static void input_linux_event(void *opaque)
static void input_linux_event_mouse(void *opaque)
{
InputLinux *il = opaque;
struct input_event event;
@@ -335,11 +282,54 @@ static void input_linux_event(void *opaque)
break;
}
if (il->num_keys) {
input_linux_handle_keyboard(il, &event);
/* only send event to guest when grab is active */
if (!il->grab_active) {
continue;
}
if (il->has_rel_x && il->num_btns) {
input_linux_handle_mouse(il, &event);
switch (event.type) {
case EV_KEY:
switch (event.code) {
case BTN_LEFT:
qemu_input_queue_btn(NULL, INPUT_BUTTON_LEFT, event.value);
break;
case BTN_RIGHT:
qemu_input_queue_btn(NULL, INPUT_BUTTON_RIGHT, event.value);
break;
case BTN_MIDDLE:
qemu_input_queue_btn(NULL, INPUT_BUTTON_MIDDLE, event.value);
break;
case BTN_GEAR_UP:
qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_UP, event.value);
break;
case BTN_GEAR_DOWN:
qemu_input_queue_btn(NULL, INPUT_BUTTON_WHEEL_DOWN,
event.value);
break;
};
break;
case EV_REL:
switch (event.code) {
case REL_X:
qemu_input_queue_rel(NULL, INPUT_AXIS_X, event.value);
break;
case REL_Y:
qemu_input_queue_rel(NULL, INPUT_AXIS_Y, event.value);
break;
case REL_WHEEL:
il->wheel = event.value;
break;
}
break;
case EV_SYN:
qemu_input_event_sync();
if (il->wheel != 0) {
input_linux_event_mouse_button((il->wheel > 0)
? INPUT_BUTTON_WHEEL_UP
: INPUT_BUTTON_WHEEL_DOWN);
il->wheel = 0;
}
break;
}
}
}
@@ -347,8 +337,7 @@ static void input_linux_event(void *opaque)
static void input_linux_complete(UserCreatable *uc, Error **errp)
{
InputLinux *il = INPUT_LINUX(uc);
uint8_t evtmap, relmap, absmap, keymap[KEY_CNT / 8];
unsigned int i;
uint32_t evtmap, relmap, absmap;
int rc, ver;
if (!il->evdev) {
@@ -376,36 +365,36 @@ static void input_linux_complete(UserCreatable *uc, Error **errp)
}
if (evtmap & (1 << EV_REL)) {
relmap = 0;
rc = ioctl(il->fd, EVIOCGBIT(EV_REL, sizeof(relmap)), &relmap);
if (relmap & (1 << REL_X)) {
il->has_rel_x = true;
if (rc < 0) {
relmap = 0;
}
}
if (evtmap & (1 << EV_ABS)) {
ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap);
if (rc < 0) {
absmap = 0;
rc = ioctl(il->fd, EVIOCGBIT(EV_ABS, sizeof(absmap)), &absmap);
if (absmap & (1 << ABS_X)) {
il->has_abs_x = true;
}
}
if (evtmap & (1 << EV_KEY)) {
memset(keymap, 0, sizeof(keymap));
rc = ioctl(il->fd, EVIOCGBIT(EV_KEY, sizeof(keymap)), keymap);
for (i = 0; i < KEY_CNT; i++) {
if (keymap[i / 8] & (1 << (i % 8))) {
if (linux_is_button(i)) {
il->num_btns++;
if ((evtmap & (1 << EV_REL)) &&
(relmap & (1 << REL_X))) {
/* has relative x axis -> assume mouse */
qemu_set_fd_handler(il->fd, input_linux_event_mouse, NULL, il);
} else if ((evtmap & (1 << EV_ABS)) &&
(absmap & (1 << ABS_X))) {
/* has absolute x axis -> not supported */
error_setg(errp, "tablet/touchscreen not supported");
goto err_close;
} else if (evtmap & (1 << EV_KEY)) {
/* has keys/buttons (and no x axis) -> assume keyboard */
qemu_set_fd_handler(il->fd, input_linux_event_keyboard, NULL, il);
} else {
il->num_keys++;
/* Huh? What is this? */
error_setg(errp, "unknown kind of input device");
goto err_close;
}
}
}
}
qemu_set_fd_handler(il->fd, input_linux_event, NULL, il);
input_linux_toggle_grab(il);
QTAILQ_INSERT_TAIL(&inputs, il, next);
il->initialized = true;