X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=hw%2Fusb-hid.c;h=aebcf032c358ce4ccbe3b7ca53fce2873baf3b02;hb=cd346349b45ef056f138a184f660b8c34c3213cc;hp=43fc47e9cb5a26deca628618083e2c6a859c74d7;hpb=47b2d338d982c9e26b2af6b51c1cc0da7cbd2b60;p=qemu diff --git a/hw/usb-hid.c b/hw/usb-hid.c index 43fc47e..aebcf03 100644 --- a/hw/usb-hid.c +++ b/hw/usb-hid.c @@ -1,9 +1,9 @@ /* * QEMU USB HID devices - * + * * Copyright (c) 2005 Fabrice Bellard * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com) - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights @@ -64,6 +64,7 @@ typedef struct USBHIDState { int kind; int protocol; int idle; + int changed; } USBHIDState; /* mostly the same values as the Bochs USB Mouse device */ @@ -95,13 +96,13 @@ static const uint8_t qemu_mouse_config_descriptor[] = { 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x04, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; + 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 50, /* u8 MaxPower; */ - + /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 @@ -123,7 +124,7 @@ static const uint8_t qemu_mouse_config_descriptor[] = { 0x01, /* u8 if_bInterfaceSubClass; */ 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ 0x07, /* u8 if_iInterface; */ - + /* HID descriptor */ 0x09, /* u8 bLength; */ 0x21, /* u8 bDescriptorType; */ @@ -150,13 +151,13 @@ static const uint8_t qemu_tablet_config_descriptor[] = { 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x05, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; + 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 50, /* u8 MaxPower; */ - + /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 @@ -205,7 +206,7 @@ static const uint8_t qemu_keyboard_config_descriptor[] = { 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x06, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; + 0xa0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, @@ -253,11 +254,11 @@ static const uint8_t qemu_keyboard_config_descriptor[] = { }; static const uint8_t qemu_mouse_hid_report_descriptor[] = { - 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, + 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, - 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, + 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, - 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, + 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x02, 0x81, 0x06, 0xC0, 0xC0, }; @@ -382,28 +383,33 @@ static const uint8_t usb_hid_usage_keys[0x100] = { 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; + hs->changed = 1; } 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; + hs->changed = 1; } 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; @@ -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))]; s->modifiers &= ~(1 << 8); + hs->changed = 1; + switch (hid_code) { case 0x00: return; @@ -456,16 +464,17 @@ static inline int int_clamp(int val, int vmin, int vmax) 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; + USBMouseState *s = &hs->ptr; 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"); s->mouse_grabbed = 1; } - + dx = int_clamp(s->dx, -128, 127); dy = int_clamp(s->dy, -128, 127); dz = int_clamp(s->dz, -128, 127); @@ -473,7 +482,7 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) s->dx -= dx; s->dy -= dy; s->dz -= dz; - + b = 0; if (s->buttons_state & MOUSE_EVENT_LBUTTON) b |= 0x01; @@ -481,7 +490,7 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) b |= 0x02; if (s->buttons_state & MOUSE_EVENT_MBUTTON) b |= 0x04; - + buf[0] = b; buf[1] = dx; buf[2] = dy; @@ -493,16 +502,17 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) 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; + USBMouseState *s = &hs->ptr; 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"); s->mouse_grabbed = 1; } - + dz = int_clamp(s->dz, -128, 127); s->dz -= dz; @@ -572,7 +582,7 @@ static void usb_keyboard_handle_reset(USBDevice *dev) { USBHIDState *s = (USBHIDState *)dev; - qemu_add_kbd_event_handler(usb_keyboard_event, &s->kbd); + qemu_add_kbd_event_handler(usb_keyboard_event, s); s->protocol = 1; } @@ -612,21 +622,21 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value, case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: - memcpy(data, qemu_mouse_dev_descriptor, + memcpy(data, qemu_mouse_dev_descriptor, sizeof(qemu_mouse_dev_descriptor)); ret = sizeof(qemu_mouse_dev_descriptor); break; case USB_DT_CONFIG: if (s->kind == USB_MOUSE) { - memcpy(data, qemu_mouse_config_descriptor, + memcpy(data, qemu_mouse_config_descriptor, sizeof(qemu_mouse_config_descriptor)); ret = sizeof(qemu_mouse_config_descriptor); } else if (s->kind == USB_TABLET) { - memcpy(data, qemu_tablet_config_descriptor, + memcpy(data, qemu_tablet_config_descriptor, sizeof(qemu_tablet_config_descriptor)); ret = sizeof(qemu_tablet_config_descriptor); } else if (s->kind == USB_KEYBOARD) { - memcpy(data, qemu_keyboard_config_descriptor, + memcpy(data, qemu_keyboard_config_descriptor, sizeof(qemu_keyboard_config_descriptor)); ret = sizeof(qemu_keyboard_config_descriptor); } @@ -692,15 +702,15 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value, switch(value >> 8) { case 0x22: if (s->kind == USB_MOUSE) { - memcpy(data, qemu_mouse_hid_report_descriptor, + memcpy(data, qemu_mouse_hid_report_descriptor, sizeof(qemu_mouse_hid_report_descriptor)); ret = sizeof(qemu_mouse_hid_report_descriptor); } else if (s->kind == USB_TABLET) { - memcpy(data, qemu_tablet_hid_report_descriptor, + memcpy(data, qemu_tablet_hid_report_descriptor, sizeof(qemu_tablet_hid_report_descriptor)); ret = sizeof(qemu_tablet_hid_report_descriptor); } else if (s->kind == USB_KEYBOARD) { - memcpy(data, qemu_keyboard_hid_report_descriptor, + memcpy(data, qemu_keyboard_hid_report_descriptor, sizeof(qemu_keyboard_hid_report_descriptor)); ret = sizeof(qemu_keyboard_hid_report_descriptor); } @@ -711,9 +721,9 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value, 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) - 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; @@ -759,10 +769,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) 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) - 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) - 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 { @@ -803,6 +817,8 @@ USBDevice *usb_tablet_init(void) 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"); @@ -824,6 +840,8 @@ USBDevice *usb_mouse_init(void) 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");