@@ -51,7 +51,12 @@ struct lenovo_drvdata {
5151 int select_right ;
5252 int sensitivity ;
5353 int press_speed ;
54- u8 middlebutton_state ; /* 0:Up, 1:Down (undecided), 2:Scrolling */
54+ /* 0: Up
55+ * 1: Down (undecided)
56+ * 2: Scrolling
57+ * 3: Patched firmware, disable workaround
58+ */
59+ u8 middlebutton_state ;
5560 bool fn_lock ;
5661};
5762
@@ -521,6 +526,19 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
521526 int ret ;
522527 struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
523528
529+ /*
530+ * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
531+ * regular keys
532+ */
533+ ret = lenovo_send_cmd_cptkbd (hdev , 0x01 , 0x03 );
534+ if (ret )
535+ hid_warn (hdev , "Failed to switch F7/9/11 mode: %d\n" , ret );
536+
537+ /* Switch middle button to native mode */
538+ ret = lenovo_send_cmd_cptkbd (hdev , 0x09 , 0x01 );
539+ if (ret )
540+ hid_warn (hdev , "Failed to switch middle button: %d\n" , ret );
541+
524542 ret = lenovo_send_cmd_cptkbd (hdev , 0x05 , cptkbd_data -> fn_lock );
525543 if (ret )
526544 hid_err (hdev , "Fn-lock setting failed: %d\n" , ret );
@@ -668,31 +686,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
668686{
669687 struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
670688
671- /* "wheel" scroll events */
672- if (usage -> type == EV_REL && (usage -> code == REL_WHEEL ||
673- usage -> code == REL_HWHEEL )) {
674- /* Scroll events disable middle-click event */
675- cptkbd_data -> middlebutton_state = 2 ;
676- return 0 ;
677- }
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 (cptkbd_data -> middlebutton_state == 1 &&
696+ usage -> type == EV_REL &&
697+ (usage -> code == REL_X || usage -> code == REL_Y )) {
698+ cptkbd_data -> middlebutton_state = 3 ;
699+ /* send middle button press which was hold before */
700+ input_event (field -> hidinput -> input ,
701+ EV_KEY , BTN_MIDDLE , 1 );
702+ input_sync (field -> hidinput -> input );
703+ }
704+
705+ /* "wheel" scroll events */
706+ if (usage -> type == EV_REL && (usage -> code == REL_WHEEL ||
707+ usage -> code == REL_HWHEEL )) {
708+ /* Scroll events disable middle-click event */
709+ cptkbd_data -> middlebutton_state = 2 ;
710+ return 0 ;
711+ }
678712
679- /* Middle click events */
680- if (usage -> type == EV_KEY && usage -> code == BTN_MIDDLE ) {
681- if (value == 1 ) {
682- cptkbd_data -> middlebutton_state = 1 ;
683- } else if (value == 0 ) {
684- if (cptkbd_data -> middlebutton_state == 1 ) {
685- /* No scrolling inbetween, send middle-click */
686- input_event (field -> hidinput -> input ,
687- EV_KEY , BTN_MIDDLE , 1 );
688- input_sync (field -> hidinput -> input );
689- input_event (field -> hidinput -> input ,
690- EV_KEY , BTN_MIDDLE , 0 );
691- input_sync (field -> hidinput -> input );
713+ /* Middle click events */
714+ if (usage -> type == EV_KEY && usage -> code == BTN_MIDDLE ) {
715+ if (value == 1 ) {
716+ cptkbd_data -> middlebutton_state = 1 ;
717+ } else if (value == 0 ) {
718+ if (cptkbd_data -> middlebutton_state == 1 ) {
719+ /* No scrolling inbetween, send middle-click */
720+ input_event (field -> hidinput -> input ,
721+ EV_KEY , BTN_MIDDLE , 1 );
722+ input_sync (field -> hidinput -> input );
723+ input_event (field -> hidinput -> input ,
724+ EV_KEY , BTN_MIDDLE , 0 );
725+ input_sync (field -> hidinput -> input );
726+ }
727+ cptkbd_data -> middlebutton_state = 0 ;
692728 }
693- cptkbd_data -> middlebutton_state = 0 ;
729+ return 1 ;
694730 }
695- return 1 ;
696731 }
697732
698733 if (usage -> type == EV_KEY && usage -> code == KEY_FN_ESC && value == 1 ) {
@@ -1126,22 +1161,6 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
11261161 }
11271162 hid_set_drvdata (hdev , cptkbd_data );
11281163
1129- /*
1130- * Tell the keyboard a driver understands it, and turn F7, F9, F11 into
1131- * regular keys (Compact only)
1132- */
1133- if (hdev -> product == USB_DEVICE_ID_LENOVO_CUSBKBD ||
1134- hdev -> product == USB_DEVICE_ID_LENOVO_CBTKBD ) {
1135- ret = lenovo_send_cmd_cptkbd (hdev , 0x01 , 0x03 );
1136- if (ret )
1137- hid_warn (hdev , "Failed to switch F7/9/11 mode: %d\n" , ret );
1138- }
1139-
1140- /* Switch middle button to native mode */
1141- ret = lenovo_send_cmd_cptkbd (hdev , 0x09 , 0x01 );
1142- if (ret )
1143- hid_warn (hdev , "Failed to switch middle button: %d\n" , ret );
1144-
11451164 /* Set keyboard settings to known state */
11461165 cptkbd_data -> middlebutton_state = 0 ;
11471166 cptkbd_data -> fn_lock = true;
@@ -1264,6 +1283,24 @@ static int lenovo_probe(struct hid_device *hdev,
12641283 return ret ;
12651284}
12661285
1286+ #ifdef CONFIG_PM
1287+ static int lenovo_reset_resume (struct hid_device * hdev )
1288+ {
1289+ switch (hdev -> product ) {
1290+ case USB_DEVICE_ID_LENOVO_CUSBKBD :
1291+ case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
1292+ if (hdev -> type == HID_TYPE_USBMOUSE )
1293+ lenovo_features_set_cptkbd (hdev );
1294+
1295+ break ;
1296+ default :
1297+ break ;
1298+ }
1299+
1300+ return 0 ;
1301+ }
1302+ #endif
1303+
12671304static void lenovo_remove_tpkbd (struct hid_device * hdev )
12681305{
12691306 struct lenovo_drvdata * data_pointer = hid_get_drvdata (hdev );
@@ -1380,6 +1417,9 @@ static struct hid_driver lenovo_driver = {
13801417 .raw_event = lenovo_raw_event ,
13811418 .event = lenovo_event ,
13821419 .report_fixup = lenovo_report_fixup ,
1420+ #ifdef CONFIG_PM
1421+ .reset_resume = lenovo_reset_resume ,
1422+ #endif
13831423};
13841424module_hid_driver (lenovo_driver );
13851425
0 commit comments