32
32
#include <linux/leds.h>
33
33
#include <linux/workqueue.h>
34
34
35
+ #if IS_ENABLED (CONFIG_ACPI_PLATFORM_PROFILE )
36
+ #include <linux/platform_profile.h>
37
+ #endif /* CONFIG_ACPI_PLATFORM_PROFILE */
38
+
35
39
#include "hid-ids.h"
36
40
37
41
/* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */
38
42
#define LENOVO_KEY_MICMUTE KEY_F20
39
43
44
+ /* HID raw events for ThinkPad X12 Tabs*/
45
+ #define TP_X12_RAW_HOTKEY_FN_F4 0x00020003
46
+ #define TP_X12_RAW_HOTKEY_FN_F8 0x38001003
47
+ #define TP_X12_RAW_HOTKEY_FN_F10 0x00000803
48
+ #define TP_X12_RAW_HOTKEY_FN_F12 0x00000403
49
+ #define TP_X12_RAW_HOTKEY_FN_SPACE 0x18001003
50
+
40
51
struct lenovo_drvdata {
41
52
u8 led_report [3 ]; /* Must be first for proper alignment */
42
53
int led_state ;
@@ -71,6 +82,14 @@ struct lenovo_drvdata {
71
82
#define TP10UBKBD_LED_OFF 1
72
83
#define TP10UBKBD_LED_ON 2
73
84
85
+ /* Function to report raw_events as key events*/
86
+ static inline void report_key_event (struct input_dev * input , int keycode )
87
+ {
88
+ input_report_key (input , keycode , 1 );
89
+ input_report_key (input , keycode , 0 );
90
+ input_sync (input );
91
+ }
92
+
74
93
static int lenovo_led_set_tp10ubkbd (struct hid_device * hdev , u8 led_code ,
75
94
enum led_brightness value )
76
95
{
@@ -472,6 +491,8 @@ static int lenovo_input_mapping(struct hid_device *hdev,
472
491
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
473
492
return lenovo_input_mapping_tp10_ultrabook_kbd (hdev , hi , field ,
474
493
usage , bit , max );
494
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
495
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
475
496
case USB_DEVICE_ID_LENOVO_X1_TAB :
476
497
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
477
498
return lenovo_input_mapping_x1_tab_kbd (hdev , hi , field , usage , bit , max );
@@ -582,6 +603,8 @@ static ssize_t attr_fn_lock_store(struct device *dev,
582
603
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
583
604
lenovo_features_set_cptkbd (hdev );
584
605
break ;
606
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
607
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
585
608
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
586
609
case USB_DEVICE_ID_LENOVO_X1_TAB :
587
610
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -680,6 +703,62 @@ static const struct attribute_group lenovo_attr_group_cptkbd = {
680
703
.attrs = lenovo_attributes_cptkbd ,
681
704
};
682
705
706
+ /* Function to handle Lenovo Thinkpad TAB X12's HID raw inputs for fn keys*/
707
+ static int lenovo_raw_event_TP_X12_tab (struct hid_device * hdev , u32 raw_data )
708
+ {
709
+ struct hid_input * hidinput ;
710
+ struct input_dev * input = NULL ;
711
+
712
+ /* Iterate through all associated input devices */
713
+ list_for_each_entry (hidinput , & hdev -> inputs , list ) {
714
+ input = hidinput -> input ;
715
+ if (!input )
716
+ continue ;
717
+
718
+ switch (raw_data ) {
719
+ /* fn-F20 being used here for MIC mute*/
720
+ case TP_X12_RAW_HOTKEY_FN_F4 :
721
+ report_key_event (input , LENOVO_KEY_MICMUTE );
722
+ return 1 ;
723
+ /* Power-mode or Airplane mode will be called based on the device*/
724
+ case TP_X12_RAW_HOTKEY_FN_F8 :
725
+ /*
726
+ * TP X12 TAB uses Fn-F8 calls Airplanemode
727
+ * Whereas TP X12 TAB2 uses Fn-F8 for toggling
728
+ * Power modes
729
+ */
730
+ if (hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ) {
731
+ report_key_event (input , KEY_RFKILL );
732
+ return 1 ;
733
+ }
734
+ #if IS_ENABLED (CONFIG_ACPI_PLATFORM_PROFILE )
735
+ else {
736
+ platform_profile_cycle ();
737
+ return 1 ;
738
+ }
739
+ #endif /* CONFIG_ACPI_PLATFORM_PROFILE */
740
+ return 0 ;
741
+ case TP_X12_RAW_HOTKEY_FN_F10 :
742
+ /* TAB1 has PICKUP Phone and TAB2 use Snipping tool*/
743
+ (hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ) ?
744
+ report_key_event (input , KEY_PICKUP_PHONE ) :
745
+ report_key_event (input , KEY_SELECTIVE_SCREENSHOT );
746
+ return 1 ;
747
+ case TP_X12_RAW_HOTKEY_FN_F12 :
748
+ /* BookMarks/STAR key*/
749
+ report_key_event (input , KEY_BOOKMARKS );
750
+ return 1 ;
751
+ case TP_X12_RAW_HOTKEY_FN_SPACE :
752
+ /* Keyboard LED backlight toggle*/
753
+ report_key_event (input , KEY_KBDILLUMTOGGLE );
754
+ return 1 ;
755
+ default :
756
+ break ;
757
+ }
758
+ }
759
+ return 0 ;
760
+ }
761
+
683
762
static int lenovo_raw_event (struct hid_device * hdev ,
684
763
struct hid_report * report , u8 * data , int size )
685
764
{
@@ -697,6 +776,15 @@ static int lenovo_raw_event(struct hid_device *hdev,
697
776
data [2 ] = 0x01 ;
698
777
}
699
778
779
+ /*
780
+ * Lenovo TP X12 Tab KBD's Fn+XX is HID raw data defined. Report ID is 0x03
781
+ * e.g.: Raw data received for MIC mute is 0x00020003.
782
+ */
783
+ if (unlikely ((hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB
784
+ || hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB2 )
785
+ && size >= 3 && report -> id == 0x03 ))
786
+ return lenovo_raw_event_TP_X12_tab (hdev , le32_to_cpu (* (u32 * )data ));
787
+
700
788
return 0 ;
701
789
}
702
790
@@ -776,6 +864,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
776
864
case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
777
865
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
778
866
return lenovo_event_cptkbd (hdev , field , usage , value );
867
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
868
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
779
869
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
780
870
case USB_DEVICE_ID_LENOVO_X1_TAB :
781
871
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1057,6 +1147,8 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
1057
1147
case USB_DEVICE_ID_LENOVO_TPKBD :
1058
1148
lenovo_led_set_tpkbd (hdev );
1059
1149
break ;
1150
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1151
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1060
1152
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1061
1153
case USB_DEVICE_ID_LENOVO_X1_TAB :
1062
1154
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1243,8 +1335,15 @@ static int lenovo_probe_tp10ubkbd(struct hid_device *hdev)
1243
1335
* We cannot read the state, only set it, so we force it to on here
1244
1336
* (which should be a no-op) to make sure that our state matches the
1245
1337
* keyboard's FN-lock state. This is the same as what Windows does.
1338
+ *
1339
+ * For X12 TAB and TAB2, the default windows behaviour Fn-lock Off.
1340
+ * Adding additional check to ensure the behaviour in case of
1341
+ * Thinkpad X12 Tabs.
1246
1342
*/
1247
- data -> fn_lock = true;
1343
+
1344
+ data -> fn_lock = !(hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ||
1345
+ hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB2 );
1346
+
1248
1347
lenovo_led_set_tp10ubkbd (hdev , TP10UBKBD_FN_LOCK_LED , data -> fn_lock );
1249
1348
1250
1349
ret = sysfs_create_group (& hdev -> dev .kobj , & lenovo_attr_group_tp10ubkbd );
@@ -1288,6 +1387,8 @@ static int lenovo_probe(struct hid_device *hdev,
1288
1387
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1289
1388
ret = lenovo_probe_cptkbd (hdev );
1290
1389
break ;
1390
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1391
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1291
1392
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1292
1393
case USB_DEVICE_ID_LENOVO_X1_TAB :
1293
1394
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1375,6 +1476,8 @@ static void lenovo_remove(struct hid_device *hdev)
1375
1476
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1376
1477
lenovo_remove_cptkbd (hdev );
1377
1478
break ;
1479
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1480
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1378
1481
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1379
1482
case USB_DEVICE_ID_LENOVO_X1_TAB :
1380
1483
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1429,6 +1532,10 @@ static const struct hid_device_id lenovo_devices[] = {
1429
1532
USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB ) },
1430
1533
{ HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1431
1534
USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB3 ) },
1535
+ { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1536
+ USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X12_TAB ) },
1537
+ { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1538
+ USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X12_TAB2 ) },
1432
1539
{ }
1433
1540
};
1434
1541
0 commit comments