This patch fixes the mouse control on the Shuttle PN31. This device is
an infrared remote with a USB receiver. It behaves as an HID keyboard
and mouse.
The mouse device sends EV_REL events with signed values, but reports
logical_minimum = logical_maximum = 64. This violates the HID spec, but
apparently works in Windows XP. On Linux it causes the HID driver to
misintepret the event values as unsigned. The attached patch (against
2.6.8) adds a new quirk to fix the behavior of this device.
I'm new to both kernel and USB hacking, so please check my work and feel
free to suggest improvements. I had a couple of specific questions:
* Is adding a quirk the correct way to handle this? Or should we apply
the fix to *all* devices where logical_minimum == logical_maximum?
* The device reports idVendor = idProduct = 0x4572, but this is not the
vendor ID assigned to Shuttle Computer Group. How should this ID be
labeled? (For now, I called it USB_VENDOR_ID_SHUTTLE_REMOTE.)
diff -upr kernel-source-2.6.8/drivers/usb/input/hid-core.c
kernel-source-2.6.8.new/drivers/usb/input/hid-core.c
--- kernel-source-2.6.8/drivers/usb/input/hid-core.c 2004-08-13 22:37:14.000000000
-0700
+++ kernel-source-2.6.8.new/drivers/usb/input/hid-core.c 2004-09-06
11:39:45.000000000 -0700
@@ -1439,6 +1439,9 @@ void hid_init_reports(struct hid_device
#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101
#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104
+#define USB_VENDOR_ID_SHUTTLE_REMOTE 0x4572
+#define USB_DEVICE_ID_SHUTTLE_PN31 0x4572
+
static struct hid_blacklist {
__u16 idVendor;
__u16 idProduct;
@@ -1521,6 +1524,8 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
+ { USB_VENDOR_ID_SHUTTLE_REMOTE, USB_DEVICE_ID_SHUTTLE_PN31,
HID_QUIRK_BAD_LOGICAL_RANGE },
+
{ 0, 0 }
};
diff -upr kernel-source-2.6.8/drivers/usb/input/hid-input.c
kernel-source-2.6.8.new/drivers/usb/input/hid-input.c
--- kernel-source-2.6.8/drivers/usb/input/hid-input.c 2004-08-13 22:36:56.000000000
-0700
+++ kernel-source-2.6.8.new/drivers/usb/input/hid-input.c 2004-09-06
11:38:39.000000000 -0700
@@ -383,6 +383,13 @@ static void hidinput_configure_usage(str
set_bit(REL_HWHEEL, bit);
}
+ if ((usage->type == EV_REL)
+ && (device->quirks & HID_QUIRK_BAD_LOGICAL_RANGE)
+ && (field->logical_minimum == field->logical_maximum)) {
+ field->logical_minimum = -127;
+ field->logical_maximum = 127;
+ }
+
while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
usage->code = find_next_zero_bit(bit, max + 1, usage->code);
}
diff -upr kernel-source-2.6.8/drivers/usb/input/hid.h
kernel-source-2.6.8.new/drivers/usb/input/hid.h
--- kernel-source-2.6.8/drivers/usb/input/hid.h 2004-08-13 22:36:10.000000000 -0700
+++ kernel-source-2.6.8.new/drivers/usb/input/hid.h 2004-09-06 11:38:39.000000000
-0700
@@ -211,6 +211,7 @@ struct hid_item {
#define HID_QUIRK_2WHEEL_MOUSE_HACK_BACK 0x080
#define HID_QUIRK_2WHEEL_MOUSE_HACK_EXTRA 0x100
#define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200
+#define HID_QUIRK_BAD_LOGICAL_RANGE 0x400
/*
* This is the global environment of the parser. This information is