diff -ur linux-2.6.11.7.orig/drivers/usb/input/hid-core.c linux/drivers/usb/input/hid-core.c --- linux-2.6.11.7.orig/drivers/usb/input/hid-core.c 2005-04-07 19:57:43.000000000 +0100 +++ linux/drivers/usb/input/hid-core.c 2005-04-18 13:34:59.000000000 +0100 @@ -1291,22 +1291,6 @@ return 0; } -static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, - unsigned char type, void *buf, int size) -{ - int result, retries = 4; - - memset(buf,0,size); // Make sure we parse really received data - - do { - result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), - USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, - (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT); - retries--; - } while (result < size && retries); - return result; -} - int hid_open(struct hid_device *hid) { if (hid->open++) @@ -1494,6 +1478,9 @@ #define USB_VENDOR_ID_DELORME 0x1163 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100 +#define USB_VENDOR_ID_CHERRY 0x046a +#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 + static struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1589,6 +1576,37 @@ { 0, 0 } }; +static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, + unsigned char type, void *buf, int size) +{ + int result, retries = 4; + char *p = (char*)buf; + + memset(buf,0,size); // Make sure we parse really received data + + do { + result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN, + (type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT); + retries--; + } while (result < size && retries); + + // wn_hack: patch wrong descriptor for this device + // hardware sends wrong descriptor + // AA, 20050418: should this test be skipped altogether if result < size? + if (dev->descriptor.idVendor == USB_VENDOR_ID_CHERRY + && dev->descriptor.idProduct == USB_DEVICE_ID_CHERRY_CYMOTION + && result > 12 + && p[11] == 0x3c + && p[12] == 0x02) { + printk(KERN_DEBUG __FILE__ " : modifying descriptor for Cherry CyMotion keyboard \n"); + p[11] = p[16] = 0xff; + p[12] = p[17] = 0x03; + } + + return result; +} + static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid) { if (!(hid->inbuf = usb_buffer_alloc(dev, HID_BUFFER_SIZE, SLAB_ATOMIC, &hid->inbuf_dma))) diff -ur linux-2.6.11.7.orig/drivers/usb/input/hid-input.c linux/drivers/usb/input/hid-input.c --- linux-2.6.11.7.orig/drivers/usb/input/hid-input.c 2005-04-07 19:57:34.000000000 +0100 +++ linux/drivers/usb/input/hid-input.c 2005-04-18 13:36:16.000000000 +0100 @@ -270,6 +270,12 @@ case 0x227: map_key_clear(KEY_REFRESH); break; case 0x22a: map_key_clear(KEY_BOOKMARKS); break; case 0x238: map_rel(REL_HWHEEL); break; + case 0x233: map_key_clear(KEY_SCROLLUP); break; + case 0x234: map_key_clear(KEY_SCROLLDOWN); break; + case 0x301: map_key_clear(KEY_PROG1); break; + case 0x302: map_key_clear(KEY_PROG2); break; + case 0x303: map_key_clear(KEY_PROG3); break; + case 0x279: map_key_clear(KEY_AGAIN); break; default: goto unknown; } break;