On Tue, 27 Feb 2007, Andrew Morton wrote:

> How'd we manage to break it between -rc4 and -final? :(
> http://bugzilla.kernel.org/show_bug.cgi?id=8099
> 
>            Summary: middle button on usb mouse not working
>     Kernel Version: 2.6.20
>             Status: NEW
>           Severity: normal
>              Owner: [EMAIL PROTECTED]
>          Submitter: [EMAIL PROTECTED]

This is a patch against 2.6.20 fixing the problem I have just queued for 
upstream in the hid tree (will push the queue to Linus shortly, after 
merging the remaining pending stuff and rebasing against 2.6.21-rc2).


From: Jiri Kosina <[EMAIL PROTECTED]>

HID: make both Logitech DiNovo Edge "touchwheel" and Logic3 /SpectraVideo 
middle button work

Dongle shipped with Logitech DiNovo Edge (0x046d/0xc714) behaves in a weird
non-standard way - it contains multiple reports with the same usage, which
results in remapping of GenericDesktop.X and GenericDesktop.Y usages to
GenericDesktop.Z and GenericDesktop.RX respectively, thus rendering the
touchwheel unusable.

The commit 35068976916fdef82d6e69ef1f8c9a1c47732759 solved this
in a way that it didn't remap certain usages. This however breaks
(at least) middle button of Logic3 / SpectraVideo (0x1267/0x0210),
which in contrary requires the remapping.

To make both of the harware work, allow remapping of these usages again,
and introduce a quirk for Logitech DiNovo Edge "touchwheel" instead - we
disable remapping for key, abs and rel events only for this hardware.

Signed-off-by: Jiri Kosina <[EMAIL PROTECTED]>

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index c7a6833..3d139d4 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -72,7 +72,6 @@ static const struct {
 #define map_led(c)     do { usage->code = c; usage->type = EV_LED; bit = 
input->ledbit; max = LED_MAX; } while (0)
 
 #define map_abs_clear(c)       do { map_abs(c); clear_bit(c, bit); } while (0)
-#define map_rel_clear(c)       do { map_rel(c); clear_bit(c, bit); } while (0)
 #define map_key_clear(c)       do { map_key(c); clear_bit(c, bit); } while (0)
 
 #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
@@ -297,7 +296,7 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
                                        }
                        }
 
-                       map_key_clear(code);
+                       map_key(code);
                        break;
 
 
@@ -348,9 +347,9 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
                                case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ:
                                case HID_GD_SLIDER: case HID_GD_DIAL: case 
HID_GD_WHEEL:
                                        if (field->flags & 
HID_MAIN_ITEM_RELATIVE)
-                                               map_rel_clear(usage->hid & 0xf);
+                                               map_rel(usage->hid & 0xf);
                                        else
-                                               map_abs_clear(usage->hid & 0xf);
+                                               map_abs(usage->hid & 0xf);
                                        break;
 
                                case HID_GD_HATSWITCH:
@@ -520,7 +519,7 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
                                case 0x22f: map_key_clear(KEY_ZOOMRESET);       
break;
                                case 0x233: map_key_clear(KEY_SCROLLUP);        
break;
                                case 0x234: map_key_clear(KEY_SCROLLDOWN);      
break;
-                               case 0x238: map_rel_clear(REL_HWHEEL);          
break;
+                               case 0x238: map_rel(REL_HWHEEL);                
break;
                                case 0x25f: map_key_clear(KEY_CANCEL);          
break;
                                case 0x279: map_key_clear(KEY_REDO);            
break;
 
@@ -648,6 +647,12 @@ static void hidinput_configure_usage(struct hid_input 
*hidinput, struct hid_fiel
 
        set_bit(usage->type, input->evbit);
 
+       if (device->quirks & HID_QUIRK_DUPLICATE_USAGES &&
+                       (usage->type == EV_KEY || 
+                        usage->type == EV_REL ||
+                        usage->type == EV_ABS))
+               clear_bit(usage->code, bit);
+
        while (usage->code <= max && test_and_set_bit(usage->code, bit))
                usage->code = find_next_zero_bit(bit, max + 1, usage->code);
 
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index c6c9e72..b2802bd 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -788,6 +788,7 @@ void usbhid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_USB_RECEIVER    0xc101
+#define USB_DEVICE_ID_LOGITECH_BT_RECEIVER     0xc714
 
 #define USB_VENDOR_ID_IMATION          0x0718
 #define USB_DEVICE_ID_DISC_STAKKA      0xd000
@@ -969,6 +970,8 @@ static const struct hid_blacklist {
 
        { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_USB_RECEIVER, 
HID_QUIRK_BAD_RELATIVE_KEYS },
 
+       { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_BT_RECEIVER, 
HID_QUIRK_DUPLICATE_USAGES },
+
        { 0, 0 }
 };
 
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 342b4e6..28216d7 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -264,6 +264,7 @@ struct hid_item {
 #define HID_QUIRK_INVERT_HWHEEL                        0x00004000
 #define HID_QUIRK_POWERBOOK_ISO_KEYBOARD        0x00008000
 #define HID_QUIRK_BAD_RELATIVE_KEYS            0x00010000
+#define HID_QUIRK_DUPLICATE_USAGES             0x00020000
 
 /*
  * This is the global environment of the parser. This information is

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to