31
31
#include <linux/input.h>
32
32
#include <linux/leds.h>
33
33
#include <linux/workqueue.h>
34
+ #include <linux/platform_profile.h>
34
35
35
36
#include "hid-ids.h"
36
37
37
38
/* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */
38
39
#define LENOVO_KEY_MICMUTE KEY_F20
39
40
41
+ /* HID raw events for ThinkPad X12 Tabs*/
42
+ #define TP_X12_RAW_HOTKEY_FN_F4 0x00020003
43
+ #define TP_X12_RAW_HOTKEY_FN_F8 0x38001003
44
+ #define TP_X12_RAW_HOTKEY_FN_F10 0x00000803
45
+ #define TP_X12_RAW_HOTKEY_FN_F12 0x00000403
46
+ #define TP_X12_RAW_HOTKEY_FN_SPACE 0x18001003
47
+
40
48
struct lenovo_drvdata {
41
49
u8 led_report [3 ]; /* Must be first for proper alignment */
42
50
int led_state ;
@@ -71,6 +79,14 @@ struct lenovo_drvdata {
71
79
#define TP10UBKBD_LED_OFF 1
72
80
#define TP10UBKBD_LED_ON 2
73
81
82
+ /* Function to report raw_events as key events*/
83
+ static inline void report_key_event (struct input_dev * input , int keycode )
84
+ {
85
+ input_report_key (input , keycode , 1 );
86
+ input_report_key (input , keycode , 0 );
87
+ input_sync (input );
88
+ }
89
+
74
90
static int lenovo_led_set_tp10ubkbd (struct hid_device * hdev , u8 led_code ,
75
91
enum led_brightness value )
76
92
{
@@ -472,6 +488,8 @@ static int lenovo_input_mapping(struct hid_device *hdev,
472
488
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
473
489
return lenovo_input_mapping_tp10_ultrabook_kbd (hdev , hi , field ,
474
490
usage , bit , max );
491
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
492
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
475
493
case USB_DEVICE_ID_LENOVO_X1_TAB :
476
494
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
477
495
return lenovo_input_mapping_x1_tab_kbd (hdev , hi , field , usage , bit , max );
@@ -582,6 +600,8 @@ static ssize_t attr_fn_lock_store(struct device *dev,
582
600
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
583
601
lenovo_features_set_cptkbd (hdev );
584
602
break ;
603
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
604
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
585
605
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
586
606
case USB_DEVICE_ID_LENOVO_X1_TAB :
587
607
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -680,6 +700,55 @@ static const struct attribute_group lenovo_attr_group_cptkbd = {
680
700
.attrs = lenovo_attributes_cptkbd ,
681
701
};
682
702
703
+ /* Function to handle Lenovo Thinkpad TAB X12's HID raw inputs for fn keys*/
704
+ static int lenovo_raw_event_TP_X12_tab (struct hid_device * hdev , u32 raw_data )
705
+ {
706
+ struct hid_input * hidinput ;
707
+ struct input_dev * input = NULL ;
708
+
709
+ /* Iterate through all associated input devices */
710
+ list_for_each_entry (hidinput , & hdev -> inputs , list ) {
711
+ input = hidinput -> input ;
712
+ if (!input )
713
+ continue ;
714
+
715
+ switch (raw_data ) {
716
+ /* fn-F20 being used here for MIC mute*/
717
+ case TP_X12_RAW_HOTKEY_FN_F4 :
718
+ report_key_event (input , LENOVO_KEY_MICMUTE );
719
+ return 1 ;
720
+ /* Power-mode or Airplane mode will be called based on the device*/
721
+ case TP_X12_RAW_HOTKEY_FN_F8 :
722
+ /*
723
+ * TP X12 TAB uses Fn-F8 calls Airplanemode
724
+ * Whereas TP X12 TAB2 uses Fn-F8 for toggling
725
+ * Power modes
726
+ */
727
+ (hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ) ?
728
+ report_key_event (input , KEY_RFKILL ) :
729
+ platform_profile_cycle ();
730
+ return 1 ;
731
+ case TP_X12_RAW_HOTKEY_FN_F10 :
732
+ /* TAB1 has PICKUP Phone and TAB2 use Snipping tool*/
733
+ (hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ) ?
734
+ report_key_event (input , KEY_PICKUP_PHONE ) :
735
+ report_key_event (input , KEY_SELECTIVE_SCREENSHOT );
736
+ return 1 ;
737
+ case TP_X12_RAW_HOTKEY_FN_F12 :
738
+ /* BookMarks/STAR key*/
739
+ report_key_event (input , KEY_BOOKMARKS );
740
+ return 1 ;
741
+ case TP_X12_RAW_HOTKEY_FN_SPACE :
742
+ /* Keyboard LED backlight toggle*/
743
+ report_key_event (input , KEY_KBDILLUMTOGGLE );
744
+ return 1 ;
745
+ default :
746
+ break ;
747
+ }
748
+ }
749
+ return 0 ;
750
+ }
751
+
683
752
static int lenovo_raw_event (struct hid_device * hdev ,
684
753
struct hid_report * report , u8 * data , int size )
685
754
{
@@ -697,6 +766,15 @@ static int lenovo_raw_event(struct hid_device *hdev,
697
766
data [2 ] = 0x01 ;
698
767
}
699
768
769
+ /*
770
+ * Lenovo TP X12 Tab KBD's Fn+XX is HID raw data defined. Report ID is 0x03
771
+ * e.g.: Raw data received for MIC mute is 0x00020003.
772
+ */
773
+ if (unlikely ((hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB
774
+ || hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB2 )
775
+ && size >= 3 && report -> id == 0x03 ))
776
+ return lenovo_raw_event_TP_X12_tab (hdev , le32_to_cpu (* (u32 * )data ));
777
+
700
778
return 0 ;
701
779
}
702
780
@@ -776,6 +854,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
776
854
case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
777
855
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
778
856
return lenovo_event_cptkbd (hdev , field , usage , value );
857
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
858
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
779
859
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
780
860
case USB_DEVICE_ID_LENOVO_X1_TAB :
781
861
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1057,6 +1137,8 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
1057
1137
case USB_DEVICE_ID_LENOVO_TPKBD :
1058
1138
lenovo_led_set_tpkbd (hdev );
1059
1139
break ;
1140
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1141
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1060
1142
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1061
1143
case USB_DEVICE_ID_LENOVO_X1_TAB :
1062
1144
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1243,8 +1325,15 @@ static int lenovo_probe_tp10ubkbd(struct hid_device *hdev)
1243
1325
* We cannot read the state, only set it, so we force it to on here
1244
1326
* (which should be a no-op) to make sure that our state matches the
1245
1327
* keyboard's FN-lock state. This is the same as what Windows does.
1328
+ *
1329
+ * For X12 TAB and TAB2, the default windows behaviour Fn-lock Off.
1330
+ * Adding additional check to ensure the behaviour in case of
1331
+ * Thinkpad X12 Tabs.
1246
1332
*/
1247
- data -> fn_lock = true;
1333
+
1334
+ data -> fn_lock = !(hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB ||
1335
+ hdev -> product == USB_DEVICE_ID_LENOVO_X12_TAB2 );
1336
+
1248
1337
lenovo_led_set_tp10ubkbd (hdev , TP10UBKBD_FN_LOCK_LED , data -> fn_lock );
1249
1338
1250
1339
ret = sysfs_create_group (& hdev -> dev .kobj , & lenovo_attr_group_tp10ubkbd );
@@ -1288,6 +1377,8 @@ static int lenovo_probe(struct hid_device *hdev,
1288
1377
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1289
1378
ret = lenovo_probe_cptkbd (hdev );
1290
1379
break ;
1380
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1381
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1291
1382
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1292
1383
case USB_DEVICE_ID_LENOVO_X1_TAB :
1293
1384
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1375,6 +1466,8 @@ static void lenovo_remove(struct hid_device *hdev)
1375
1466
case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
1376
1467
lenovo_remove_cptkbd (hdev );
1377
1468
break ;
1469
+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1470
+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
1378
1471
case USB_DEVICE_ID_LENOVO_TP10UBKBD :
1379
1472
case USB_DEVICE_ID_LENOVO_X1_TAB :
1380
1473
case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1429,6 +1522,10 @@ static const struct hid_device_id lenovo_devices[] = {
1429
1522
USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB ) },
1430
1523
{ HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1431
1524
USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB3 ) },
1525
+ { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1526
+ USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X12_TAB ) },
1527
+ { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
1528
+ USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X12_TAB2 ) },
1432
1529
{ }
1433
1530
};
1434
1531
0 commit comments