@@ -54,10 +54,10 @@ struct lenovo_drvdata {
5454 /* 0: Up
5555 * 1: Down (undecided)
5656 * 2: Scrolling
57- * 3: Patched firmware, disable workaround
5857 */
5958 u8 middlebutton_state ;
6059 bool fn_lock ;
60+ bool middleclick_workaround_cptkbd ;
6161};
6262
6363#define map_key_clear (c ) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
@@ -621,6 +621,36 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
621621 return count ;
622622}
623623
624+ static ssize_t attr_middleclick_workaround_show_cptkbd (struct device * dev ,
625+ struct device_attribute * attr ,
626+ char * buf )
627+ {
628+ struct hid_device * hdev = to_hid_device (dev );
629+ struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
630+
631+ return snprintf (buf , PAGE_SIZE , "%u\n" ,
632+ cptkbd_data -> middleclick_workaround_cptkbd );
633+ }
634+
635+ static ssize_t attr_middleclick_workaround_store_cptkbd (struct device * dev ,
636+ struct device_attribute * attr ,
637+ const char * buf ,
638+ size_t count )
639+ {
640+ struct hid_device * hdev = to_hid_device (dev );
641+ struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
642+ int value ;
643+
644+ if (kstrtoint (buf , 10 , & value ))
645+ return - EINVAL ;
646+ if (value < 0 || value > 1 )
647+ return - EINVAL ;
648+
649+ cptkbd_data -> middleclick_workaround_cptkbd = !!value ;
650+
651+ return count ;
652+ }
653+
624654
625655static struct device_attribute dev_attr_fn_lock =
626656 __ATTR (fn_lock , S_IWUSR | S_IRUGO ,
@@ -632,10 +662,16 @@ static struct device_attribute dev_attr_sensitivity_cptkbd =
632662 attr_sensitivity_show_cptkbd ,
633663 attr_sensitivity_store_cptkbd );
634664
665+ static struct device_attribute dev_attr_middleclick_workaround_cptkbd =
666+ __ATTR (middleclick_workaround , S_IWUSR | S_IRUGO ,
667+ attr_middleclick_workaround_show_cptkbd ,
668+ attr_middleclick_workaround_store_cptkbd );
669+
635670
636671static struct attribute * lenovo_attributes_cptkbd [] = {
637672 & dev_attr_fn_lock .attr ,
638673 & dev_attr_sensitivity_cptkbd .attr ,
674+ & dev_attr_middleclick_workaround_cptkbd .attr ,
639675 NULL
640676};
641677
@@ -686,23 +722,7 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
686722{
687723 struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
688724
689- if (cptkbd_data -> middlebutton_state != 3 ) {
690- /* REL_X and REL_Y events during middle button pressed
691- * are only possible on patched, bug-free firmware
692- * so set middlebutton_state to 3
693- * to never apply workaround anymore
694- */
695- if (hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD &&
696- cptkbd_data -> middlebutton_state == 1 &&
697- usage -> type == EV_REL &&
698- (usage -> code == REL_X || usage -> code == REL_Y )) {
699- cptkbd_data -> middlebutton_state = 3 ;
700- /* send middle button press which was hold before */
701- input_event (field -> hidinput -> input ,
702- EV_KEY , BTN_MIDDLE , 1 );
703- input_sync (field -> hidinput -> input );
704- }
705-
725+ if (cptkbd_data -> middleclick_workaround_cptkbd ) {
706726 /* "wheel" scroll events */
707727 if (usage -> type == EV_REL && (usage -> code == REL_WHEEL ||
708728 usage -> code == REL_HWHEEL )) {
@@ -1166,6 +1186,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
11661186 cptkbd_data -> middlebutton_state = 0 ;
11671187 cptkbd_data -> fn_lock = true;
11681188 cptkbd_data -> sensitivity = 0x05 ;
1189+ cptkbd_data -> middleclick_workaround_cptkbd = true;
11691190 lenovo_features_set_cptkbd (hdev );
11701191
11711192 ret = sysfs_create_group (& hdev -> dev .kobj , & lenovo_attr_group_cptkbd );
0 commit comments