Commit 117b3ae6e6d27ea31e85ffe1820437d91269ed4e

Authored by pbrook
1 parent ead9360e

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
Showing 2 changed files with 33 additions and 12 deletions
hw/usb-hid.c
@@ -64,6 +64,7 @@ typedef struct USBHIDState { @@ -64,6 +64,7 @@ typedef struct USBHIDState {
64 int kind; 64 int kind;
65 int protocol; 65 int protocol;
66 int idle; 66 int idle;
  67 + int changed;
67 } USBHIDState; 68 } USBHIDState;
68 69
69 /* mostly the same values as the Bochs USB Mouse device */ 70 /* mostly the same values as the Bochs USB Mouse device */
@@ -382,28 +383,33 @@ static const uint8_t usb_hid_usage_keys[0x100] = { @@ -382,28 +383,33 @@ static const uint8_t usb_hid_usage_keys[0x100] = {
382 static void usb_mouse_event(void *opaque, 383 static void usb_mouse_event(void *opaque,
383 int dx1, int dy1, int dz1, int buttons_state) 384 int dx1, int dy1, int dz1, int buttons_state)
384 { 385 {
385 - USBMouseState *s = opaque; 386 + USBHIDState *hs = opaque;
  387 + USBMouseState *s = &hs->ptr;
386 388
387 s->dx += dx1; 389 s->dx += dx1;
388 s->dy += dy1; 390 s->dy += dy1;
389 s->dz += dz1; 391 s->dz += dz1;
390 s->buttons_state = buttons_state; 392 s->buttons_state = buttons_state;
  393 + hs->changed = 1;
391 } 394 }
392 395
393 static void usb_tablet_event(void *opaque, 396 static void usb_tablet_event(void *opaque,
394 int x, int y, int dz, int buttons_state) 397 int x, int y, int dz, int buttons_state)
395 { 398 {
396 - USBMouseState *s = opaque; 399 + USBHIDState *hs = opaque;
  400 + USBMouseState *s = &hs->ptr;
397 401
398 s->x = x; 402 s->x = x;
399 s->y = y; 403 s->y = y;
400 s->dz += dz; 404 s->dz += dz;
401 s->buttons_state = buttons_state; 405 s->buttons_state = buttons_state;
  406 + hs->changed = 1;
402 } 407 }
403 408
404 static void usb_keyboard_event(void *opaque, int keycode) 409 static void usb_keyboard_event(void *opaque, int keycode)
405 { 410 {
406 - USBKeyboardState *s = opaque; 411 + USBHIDState *hs = opaque;
  412 + USBKeyboardState *s = &hs->kbd;
407 uint8_t hid_code, key; 413 uint8_t hid_code, key;
408 int i; 414 int i;
409 415
@@ -411,6 +417,8 @@ static void usb_keyboard_event(void *opaque, int keycode) @@ -411,6 +417,8 @@ static void usb_keyboard_event(void *opaque, int keycode)
411 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; 417 hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
412 s->modifiers &= ~(1 << 8); 418 s->modifiers &= ~(1 << 8);
413 419
  420 + hs->changed = 1;
  421 +
414 switch (hid_code) { 422 switch (hid_code) {
415 case 0x00: 423 case 0x00:
416 return; 424 return;
@@ -456,12 +464,13 @@ static inline int int_clamp(int val, int vmin, int vmax) @@ -456,12 +464,13 @@ static inline int int_clamp(int val, int vmin, int vmax)
456 return val; 464 return val;
457 } 465 }
458 466
459 -static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) 467 +static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
460 { 468 {
461 int dx, dy, dz, b, l; 469 int dx, dy, dz, b, l;
  470 + USBMouseState *s = &hs->ptr;
462 471
463 if (!s->mouse_grabbed) { 472 if (!s->mouse_grabbed) {
464 - s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 473 + s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs,
465 0, "QEMU USB Mouse"); 474 0, "QEMU USB Mouse");
466 s->mouse_grabbed = 1; 475 s->mouse_grabbed = 1;
467 } 476 }
@@ -493,12 +502,13 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) @@ -493,12 +502,13 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
493 return l; 502 return l;
494 } 503 }
495 504
496 -static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len) 505 +static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
497 { 506 {
498 int dz, b, l; 507 int dz, b, l;
  508 + USBMouseState *s = &hs->ptr;
499 509
500 if (!s->mouse_grabbed) { 510 if (!s->mouse_grabbed) {
501 - s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s, 511 + s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs,
502 1, "QEMU USB Tablet"); 512 1, "QEMU USB Tablet");
503 s->mouse_grabbed = 1; 513 s->mouse_grabbed = 1;
504 } 514 }
@@ -711,9 +721,9 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value, @@ -711,9 +721,9 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
711 break; 721 break;
712 case GET_REPORT: 722 case GET_REPORT:
713 if (s->kind == USB_MOUSE) 723 if (s->kind == USB_MOUSE)
714 - ret = usb_mouse_poll(&s->ptr, data, length); 724 + ret = usb_mouse_poll(s, data, length);
715 else if (s->kind == USB_TABLET) 725 else if (s->kind == USB_TABLET)
716 - ret = usb_tablet_poll(&s->ptr, data, length); 726 + ret = usb_tablet_poll(s, data, length);
717 else if (s->kind == USB_KEYBOARD) 727 else if (s->kind == USB_KEYBOARD)
718 ret = usb_keyboard_poll(&s->kbd, data, length); 728 ret = usb_keyboard_poll(&s->kbd, data, length);
719 break; 729 break;
@@ -759,10 +769,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) @@ -759,10 +769,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
759 switch(p->pid) { 769 switch(p->pid) {
760 case USB_TOKEN_IN: 770 case USB_TOKEN_IN:
761 if (p->devep == 1) { 771 if (p->devep == 1) {
  772 + /* TODO: Implement finite idle delays. */
  773 + if (!(s->changed || s->idle))
  774 + return USB_RET_NAK;
  775 + s->changed = 0;
762 if (s->kind == USB_MOUSE) 776 if (s->kind == USB_MOUSE)
763 - ret = usb_mouse_poll(&s->ptr, p->data, p->len); 777 + ret = usb_mouse_poll(s, p->data, p->len);
764 else if (s->kind == USB_TABLET) 778 else if (s->kind == USB_TABLET)
765 - ret = usb_tablet_poll(&s->ptr, p->data, p->len); 779 + ret = usb_tablet_poll(s, p->data, p->len);
766 else if (s->kind == USB_KEYBOARD) 780 else if (s->kind == USB_KEYBOARD)
767 ret = usb_keyboard_poll(&s->kbd, p->data, p->len); 781 ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
768 } else { 782 } else {
@@ -803,6 +817,8 @@ USBDevice *usb_tablet_init(void) @@ -803,6 +817,8 @@ USBDevice *usb_tablet_init(void)
803 s->dev.handle_data = usb_hid_handle_data; 817 s->dev.handle_data = usb_hid_handle_data;
804 s->dev.handle_destroy = usb_hid_handle_destroy; 818 s->dev.handle_destroy = usb_hid_handle_destroy;
805 s->kind = USB_TABLET; 819 s->kind = USB_TABLET;
  820 + /* Force poll routine to be run and grab input the first time. */
  821 + s->changed = 1;
806 822
807 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); 823 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet");
808 824
@@ -824,6 +840,8 @@ USBDevice *usb_mouse_init(void) @@ -824,6 +840,8 @@ USBDevice *usb_mouse_init(void)
824 s->dev.handle_data = usb_hid_handle_data; 840 s->dev.handle_data = usb_hid_handle_data;
825 s->dev.handle_destroy = usb_hid_handle_destroy; 841 s->dev.handle_destroy = usb_hid_handle_destroy;
826 s->kind = USB_MOUSE; 842 s->kind = USB_MOUSE;
  843 + /* Force poll routine to be run and grab input the first time. */
  844 + s->changed = 1;
827 845
828 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); 846 pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse");
829 847
hw/usb-uhci.c
@@ -526,7 +526,10 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask) @@ -526,7 +526,10 @@ static int uhci_handle_td(UHCIState *s, UHCI_TD *td, int *int_mask)
526 td->ctrl &= ~TD_CTRL_ACTIVE; 526 td->ctrl &= ~TD_CTRL_ACTIVE;
527 if (ret >= 0) { 527 if (ret >= 0) {
528 td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff); 528 td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
529 - td->ctrl &= ~TD_CTRL_ACTIVE; 529 + /* The NAK bit may have been set by a previous frame, so clear it
  530 + here. The docs are somewhat unclear, but win2k relies on this
  531 + behavior. */
  532 + td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);
530 if (pid == USB_TOKEN_IN && 533 if (pid == USB_TOKEN_IN &&
531 (td->ctrl & TD_CTRL_SPD) && 534 (td->ctrl & TD_CTRL_SPD) &&
532 len < max_len) { 535 len < max_len) {