HID: lenovo: Detect quirk-free fw on cptkbd and stop applying workaround
[linux-2.6-microblaze.git] / drivers / hid / hid-lenovo.c
index 44763c0..9c11813 100644 (file)
@@ -51,7 +51,12 @@ struct lenovo_drvdata {
        int select_right;
        int sensitivity;
        int press_speed;
-       u8 middlebutton_state; /* 0:Up, 1:Down (undecided), 2:Scrolling */
+       /* 0: Up
+        * 1: Down (undecided)
+        * 2: Scrolling
+        * 3: Patched firmware, disable workaround
+        */
+       u8 middlebutton_state;
        bool fn_lock;
 };
 
@@ -668,31 +673,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
 {
        struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
 
-       /* "wheel" scroll events */
-       if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
-                       usage->code == REL_HWHEEL)) {
-               /* Scroll events disable middle-click event */
-               cptkbd_data->middlebutton_state = 2;
-               return 0;
-       }
+       if (cptkbd_data->middlebutton_state != 3) {
+               /* REL_X and REL_Y events during middle button pressed
+                * are only possible on patched, bug-free firmware
+                * so set middlebutton_state to 3
+                * to never apply workaround anymore
+                */
+               if (cptkbd_data->middlebutton_state == 1 &&
+                               usage->type == EV_REL &&
+                               (usage->code == REL_X || usage->code == REL_Y)) {
+                       cptkbd_data->middlebutton_state = 3;
+                       /* send middle button press which was hold before */
+                       input_event(field->hidinput->input,
+                               EV_KEY, BTN_MIDDLE, 1);
+                       input_sync(field->hidinput->input);
+               }
 
-       /* Middle click events */
-       if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
-               if (value == 1) {
-                       cptkbd_data->middlebutton_state = 1;
-               } else if (value == 0) {
-                       if (cptkbd_data->middlebutton_state == 1) {
-                               /* No scrolling inbetween, send middle-click */
-                               input_event(field->hidinput->input,
-                                       EV_KEY, BTN_MIDDLE, 1);
-                               input_sync(field->hidinput->input);
-                               input_event(field->hidinput->input,
-                                       EV_KEY, BTN_MIDDLE, 0);
-                               input_sync(field->hidinput->input);
+               /* "wheel" scroll events */
+               if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
+                               usage->code == REL_HWHEEL)) {
+                       /* Scroll events disable middle-click event */
+                       cptkbd_data->middlebutton_state = 2;
+                       return 0;
+               }
+
+               /* Middle click events */
+               if (usage->type == EV_KEY && usage->code == BTN_MIDDLE) {
+                       if (value == 1) {
+                               cptkbd_data->middlebutton_state = 1;
+                       } else if (value == 0) {
+                               if (cptkbd_data->middlebutton_state == 1) {
+                                       /* No scrolling inbetween, send middle-click */
+                                       input_event(field->hidinput->input,
+                                               EV_KEY, BTN_MIDDLE, 1);
+                                       input_sync(field->hidinput->input);
+                                       input_event(field->hidinput->input,
+                                               EV_KEY, BTN_MIDDLE, 0);
+                                       input_sync(field->hidinput->input);
+                               }
+                               cptkbd_data->middlebutton_state = 0;
                        }
-                       cptkbd_data->middlebutton_state = 0;
+                       return 1;
                }
-               return 1;
        }
 
        if (usage->type == EV_KEY && usage->code == KEY_FN_ESC && value == 1) {