Add PowerPC power-management state check callback.
[qemu] / hw / usb-hid.c
index 43fc47e..aebcf03 100644 (file)
@@ -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");