mirror of
https://git.proxmox.com/git/qemu
synced 2025-08-07 09:40:44 +00:00
Implement HID idle mode (avoids flooding guest with useless updates).
Fix UHCI NACK bug. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3157 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
ead9360e2f
commit
117b3ae6e6
40
hw/usb-hid.c
40
hw/usb-hid.c
@ -64,6 +64,7 @@ typedef struct USBHIDState {
|
|||||||
int kind;
|
int kind;
|
||||||
int protocol;
|
int protocol;
|
||||||
int idle;
|
int idle;
|
||||||
|
int changed;
|
||||||
} USBHIDState;
|
} USBHIDState;
|
||||||
|
|
||||||
/* mostly the same values as the Bochs USB Mouse device */
|
/* mostly the same values as the Bochs USB Mouse device */
|
||||||
@ -382,28 +383,33 @@ static const uint8_t usb_hid_usage_keys[0x100] = {
|
|||||||
static void usb_mouse_event(void *opaque,
|
static void usb_mouse_event(void *opaque,
|
||||||
int dx1, int dy1, int dz1, int buttons_state)
|
int dx1, int dy1, int dz1, int buttons_state)
|
||||||
{
|
{
|
||||||
USBMouseState *s = opaque;
|
USBHIDState *hs = opaque;
|
||||||
|
USBMouseState *s = &hs->ptr;
|
||||||
|
|
||||||
s->dx += dx1;
|
s->dx += dx1;
|
||||||
s->dy += dy1;
|
s->dy += dy1;
|
||||||
s->dz += dz1;
|
s->dz += dz1;
|
||||||
s->buttons_state = buttons_state;
|
s->buttons_state = buttons_state;
|
||||||
|
hs->changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_tablet_event(void *opaque,
|
static void usb_tablet_event(void *opaque,
|
||||||
int x, int y, int dz, int buttons_state)
|
int x, int y, int dz, int buttons_state)
|
||||||
{
|
{
|
||||||
USBMouseState *s = opaque;
|
USBHIDState *hs = opaque;
|
||||||
|
USBMouseState *s = &hs->ptr;
|
||||||
|
|
||||||
s->x = x;
|
s->x = x;
|
||||||
s->y = y;
|
s->y = y;
|
||||||
s->dz += dz;
|
s->dz += dz;
|
||||||
s->buttons_state = buttons_state;
|
s->buttons_state = buttons_state;
|
||||||
|
hs->changed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_keyboard_event(void *opaque, int keycode)
|
static void usb_keyboard_event(void *opaque, int keycode)
|
||||||
{
|
{
|
||||||
USBKeyboardState *s = opaque;
|
USBHIDState *hs = opaque;
|
||||||
|
USBKeyboardState *s = &hs->kbd;
|
||||||
uint8_t hid_code, key;
|
uint8_t hid_code, key;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -411,6 +417,8 @@ static void usb_keyboard_event(void *opaque, int keycode)
|
|||||||
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
|
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
|
||||||
s->modifiers &= ~(1 << 8);
|
s->modifiers &= ~(1 << 8);
|
||||||
|
|
||||||
|
hs->changed = 1;
|
||||||
|
|
||||||
switch (hid_code) {
|
switch (hid_code) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
return;
|
return;
|
||||||
@ -456,12 +464,13 @@ static inline int int_clamp(int val, int vmin, int vmax)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
|
static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int dx, dy, dz, b, l;
|
int dx, dy, dz, b, l;
|
||||||
|
USBMouseState *s = &hs->ptr;
|
||||||
|
|
||||||
if (!s->mouse_grabbed) {
|
if (!s->mouse_grabbed) {
|
||||||
s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
|
s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
|
||||||
0, "QEMU USB Mouse");
|
0, "QEMU USB Mouse");
|
||||||
s->mouse_grabbed = 1;
|
s->mouse_grabbed = 1;
|
||||||
}
|
}
|
||||||
@ -493,12 +502,13 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
|
static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
|
||||||
{
|
{
|
||||||
int dz, b, l;
|
int dz, b, l;
|
||||||
|
USBMouseState *s = &hs->ptr;
|
||||||
|
|
||||||
if (!s->mouse_grabbed) {
|
if (!s->mouse_grabbed) {
|
||||||
s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
|
s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
|
||||||
1, "QEMU USB Tablet");
|
1, "QEMU USB Tablet");
|
||||||
s->mouse_grabbed = 1;
|
s->mouse_grabbed = 1;
|
||||||
}
|
}
|
||||||
@ -711,9 +721,9 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
|
|||||||
break;
|
break;
|
||||||
case GET_REPORT:
|
case GET_REPORT:
|
||||||
if (s->kind == USB_MOUSE)
|
if (s->kind == USB_MOUSE)
|
||||||
ret = usb_mouse_poll(&s->ptr, data, length);
|
ret = usb_mouse_poll(s, data, length);
|
||||||
else if (s->kind == USB_TABLET)
|
else if (s->kind == USB_TABLET)
|
||||||
ret = usb_tablet_poll(&s->ptr, data, length);
|
ret = usb_tablet_poll(s, data, length);
|
||||||
else if (s->kind == USB_KEYBOARD)
|
else if (s->kind == USB_KEYBOARD)
|
||||||
ret = usb_keyboard_poll(&s->kbd, data, length);
|
ret = usb_keyboard_poll(&s->kbd, data, length);
|
||||||
break;
|
break;
|
||||||
@ -759,10 +769,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
|
|||||||
switch(p->pid) {
|
switch(p->pid) {
|
||||||
case USB_TOKEN_IN:
|
case USB_TOKEN_IN:
|
||||||
if (p->devep == 1) {
|
if (p->devep == 1) {
|
||||||
|
/* TODO: Implement finite idle delays. */
|
||||||
|
if (!(s->changed || s->idle))
|
||||||
|
return USB_RET_NAK;
|
||||||
|
s->changed = 0;
|
||||||
if (s->kind == USB_MOUSE)
|
if (s->kind == USB_MOUSE)
|
||||||
ret = usb_mouse_poll(&s->ptr, p->data, p->len);
|
ret = usb_mouse_poll(s, p->data, p->len);
|
||||||
else if (s->kind == USB_TABLET)
|
else if (s->kind == USB_TABLET)
|
||||||
ret = usb_tablet_poll(&s->ptr, p->data, p->len);
|
ret = usb_tablet_poll(s, p->data, p->len);
|
||||||
else if (s->kind == USB_KEYBOARD)
|
else if (s->kind == USB_KEYBOARD)
|
||||||
ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
|
ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
|
||||||
} else {
|
} else {
|
||||||
@ -803,6 +817,8 @@ USBDevice *usb_tablet_init(void)
|
|||||||
s->dev.handle_data = usb_hid_handle_data;
|
s->dev.handle_data = usb_hid_handle_data;
|
||||||
s->dev.handle_destroy = usb_hid_handle_destroy;
|
s->dev.handle_destroy = usb_hid_handle_destroy;
|
||||||
s->kind = USB_TABLET;
|
s->kind = USB_TABLET;
|
||||||
|
/* Force poll routine to be run and grab input the first time. */
|
||||||
|
s->changed = 1;
|
||||||
|
|
||||||
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
|
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
|
||||||
|
|
||||||
@ -824,6 +840,8 @@ USBDevice *usb_mouse_init(void)
|
|||||||
s->dev.handle_data = usb_hid_handle_data;
|
s->dev.handle_data = usb_hid_handle_data;
|
||||||
s->dev.handle_destroy = usb_hid_handle_destroy;
|
s->dev.handle_destroy = usb_hid_handle_destroy;
|
||||||
s->kind = USB_MOUSE;
|
s->kind = USB_MOUSE;
|
||||||
|
/* Force poll routine to be run and grab input the first time. */
|
||||||
|
s->changed = 1;
|
||||||
|
|
||||||
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
|
pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
|
||||||
|
|
||||||
|
@ -526,7 +526,10 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
|
|||||||
td->ctrl &= ~TD_CTRL_ACTIVE;
|
td->ctrl &= ~TD_CTRL_ACTIVE;
|
||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
|
td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
|
||||||
td->ctrl &= ~TD_CTRL_ACTIVE;
|
/* The NAK bit may have been set by a previous frame, so clear it
|
||||||
|
here. The docs are somewhat unclear, but win2k relies on this
|
||||||
|
behavior. */
|
||||||
|
td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
|
||||||
if (pid == USB_TOKEN_IN &&
|
if (pid == USB_TOKEN_IN &&
|
||||||
(td->ctrl & TD_CTRL_SPD) &&
|
(td->ctrl & TD_CTRL_SPD) &&
|
||||||
len < max_len) {
|
len < max_len) {
|
||||||
|
Loading…
Reference in New Issue
Block a user