@@ -51,7 +51,12 @@ struct lenovo_drvdata {
51
51
int select_right ;
52
52
int sensitivity ;
53
53
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 ;
55
60
bool fn_lock ;
56
61
};
57
62
@@ -521,6 +526,19 @@ static void lenovo_features_set_cptkbd(struct hid_device *hdev)
521
526
int ret ;
522
527
struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
523
528
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
+
524
542
ret = lenovo_send_cmd_cptkbd (hdev , 0x05 , cptkbd_data -> fn_lock );
525
543
if (ret )
526
544
hid_err (hdev , "Fn-lock setting failed: %d\n" , ret );
@@ -668,31 +686,48 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
668
686
{
669
687
struct lenovo_drvdata * cptkbd_data = hid_get_drvdata (hdev );
670
688
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
+ }
678
712
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 ;
692
728
}
693
- cptkbd_data -> middlebutton_state = 0 ;
729
+ return 1 ;
694
730
}
695
- return 1 ;
696
731
}
697
732
698
733
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)
1126
1161
}
1127
1162
hid_set_drvdata (hdev , cptkbd_data );
1128
1163
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
-
1145
1164
/* Set keyboard settings to known state */
1146
1165
cptkbd_data -> middlebutton_state = 0 ;
1147
1166
cptkbd_data -> fn_lock = true;
@@ -1264,6 +1283,24 @@ static int lenovo_probe(struct hid_device *hdev,
1264
1283
return ret ;
1265
1284
}
1266
1285
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
+
1267
1304
static void lenovo_remove_tpkbd (struct hid_device * hdev )
1268
1305
{
1269
1306
struct lenovo_drvdata * data_pointer = hid_get_drvdata (hdev );
@@ -1380,6 +1417,9 @@ static struct hid_driver lenovo_driver = {
1380
1417
.raw_event = lenovo_raw_event ,
1381
1418
.event = lenovo_event ,
1382
1419
.report_fixup = lenovo_report_fixup ,
1420
+ #ifdef CONFIG_PM
1421
+ .reset_resume = lenovo_reset_resume ,
1422
+ #endif
1383
1423
};
1384
1424
module_hid_driver (lenovo_driver );
1385
1425
0 commit comments