Fix UHCI NACK bug.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3157
c046a42c-6fe2-441c-8c8c-
71466251a162
int kind;
int protocol;
int idle;
int kind;
int protocol;
int idle;
} USBHIDState;
/* mostly the same values as the Bochs USB Mouse device */
} USBHIDState;
/* mostly the same values as the Bochs USB Mouse device */
static void usb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
static void usb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
- USBMouseState *s = opaque;
+ USBHIDState *hs = opaque;
+ USBMouseState *s = &hs->ptr;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
}
static void usb_tablet_event(void *opaque,
int x, int y, int dz, int buttons_state)
{
}
static void usb_tablet_event(void *opaque,
int x, int y, int dz, int buttons_state)
{
- USBMouseState *s = opaque;
+ USBHIDState *hs = opaque;
+ USBMouseState *s = &hs->ptr;
s->x = x;
s->y = y;
s->dz += dz;
s->buttons_state = buttons_state;
s->x = x;
s->y = y;
s->dz += dz;
s->buttons_state = buttons_state;
}
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;
int i;
uint8_t hid_code, key;
int i;
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
s->modifiers &= ~(1 << 8);
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
s->modifiers &= ~(1 << 8);
switch (hid_code) {
case 0x00:
return;
switch (hid_code) {
case 0x00:
return;
-static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len)
+static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
+ USBMouseState *s = &hs->ptr;
- 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");
s->mouse_grabbed = 1;
}
0, "QEMU USB Mouse");
s->mouse_grabbed = 1;
}
-static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len)
+static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
+ USBMouseState *s = &hs->ptr;
- 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");
s->mouse_grabbed = 1;
}
1, "QEMU USB Tablet");
s->mouse_grabbed = 1;
}
break;
case GET_REPORT:
if (s->kind == USB_MOUSE)
break;
case GET_REPORT:
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)
ret = usb_keyboard_poll(&s->kbd, data, length);
break;
else if (s->kind == USB_KEYBOARD)
ret = usb_keyboard_poll(&s->kbd, data, length);
break;
switch(p->pid) {
case USB_TOKEN_IN:
if (p->devep == 1) {
switch(p->pid) {
case USB_TOKEN_IN:
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)
ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
} else {
else if (s->kind == USB_KEYBOARD)
ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
} else {
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
s->kind = USB_TABLET;
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
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");
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
s->kind = USB_MOUSE;
s->dev.handle_data = usb_hid_handle_data;
s->dev.handle_destroy = usb_hid_handle_destroy;
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");
td->ctrl &= ~TD_CTRL_ACTIVE;
if (ret >= 0) {
td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);
td->ctrl &= ~TD_CTRL_ACTIVE;
if (ret >= 0) {
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 &&
(td->ctrl & TD_CTRL_SPD) &&
len < max_len) {
if (pid == USB_TOKEN_IN &&
(td->ctrl & TD_CTRL_SPD) &&
len < max_len) {