3232#include <linux/leds.h>
3333#include <linux/workqueue.h>
3434
35+ #if IS_ENABLED (CONFIG_ACPI_PLATFORM_PROFILE )
36+ #include <linux/platform_profile.h>
37+ #endif /* CONFIG_ACPI_PLATFORM_PROFILE */
38+
3539#include "hid-ids.h"
3640
3741/* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */
3842#define LENOVO_KEY_MICMUTE KEY_F20
3943
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+
4051struct lenovo_drvdata {
4152 u8 led_report [3 ]; /* Must be first for proper alignment */
4253 int led_state ;
@@ -71,6 +82,14 @@ struct lenovo_drvdata {
7182#define TP10UBKBD_LED_OFF 1
7283#define TP10UBKBD_LED_ON 2
7384
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+
7493static int lenovo_led_set_tp10ubkbd (struct hid_device * hdev , u8 led_code ,
7594 enum led_brightness value )
7695{
@@ -472,6 +491,8 @@ static int lenovo_input_mapping(struct hid_device *hdev,
472491 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
473492 return lenovo_input_mapping_tp10_ultrabook_kbd (hdev , hi , field ,
474493 usage , bit , max );
494+ case USB_DEVICE_ID_LENOVO_X12_TAB :
495+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
475496 case USB_DEVICE_ID_LENOVO_X1_TAB :
476497 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
477498 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,
582603 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
583604 lenovo_features_set_cptkbd (hdev );
584605 break ;
606+ case USB_DEVICE_ID_LENOVO_X12_TAB :
607+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
585608 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
586609 case USB_DEVICE_ID_LENOVO_X1_TAB :
587610 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -680,6 +703,62 @@ static const struct attribute_group lenovo_attr_group_cptkbd = {
680703 .attrs = lenovo_attributes_cptkbd ,
681704};
682705
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+
683762static int lenovo_raw_event (struct hid_device * hdev ,
684763 struct hid_report * report , u8 * data , int size )
685764{
@@ -697,6 +776,15 @@ static int lenovo_raw_event(struct hid_device *hdev,
697776 data [2 ] = 0x01 ;
698777 }
699778
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+
700788 return 0 ;
701789}
702790
@@ -776,6 +864,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
776864 case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
777865 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
778866 return lenovo_event_cptkbd (hdev , field , usage , value );
867+ case USB_DEVICE_ID_LENOVO_X12_TAB :
868+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
779869 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
780870 case USB_DEVICE_ID_LENOVO_X1_TAB :
781871 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1057,6 +1147,8 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
10571147 case USB_DEVICE_ID_LENOVO_TPKBD :
10581148 lenovo_led_set_tpkbd (hdev );
10591149 break ;
1150+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1151+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
10601152 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
10611153 case USB_DEVICE_ID_LENOVO_X1_TAB :
10621154 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1243,8 +1335,15 @@ static int lenovo_probe_tp10ubkbd(struct hid_device *hdev)
12431335 * We cannot read the state, only set it, so we force it to on here
12441336 * (which should be a no-op) to make sure that our state matches the
12451337 * 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.
12461342 */
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+
12481347 lenovo_led_set_tp10ubkbd (hdev , TP10UBKBD_FN_LOCK_LED , data -> fn_lock );
12491348
12501349 ret = sysfs_create_group (& hdev -> dev .kobj , & lenovo_attr_group_tp10ubkbd );
@@ -1288,6 +1387,8 @@ static int lenovo_probe(struct hid_device *hdev,
12881387 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
12891388 ret = lenovo_probe_cptkbd (hdev );
12901389 break ;
1390+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1391+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
12911392 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
12921393 case USB_DEVICE_ID_LENOVO_X1_TAB :
12931394 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1375,6 +1476,8 @@ static void lenovo_remove(struct hid_device *hdev)
13751476 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
13761477 lenovo_remove_cptkbd (hdev );
13771478 break ;
1479+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1480+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
13781481 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
13791482 case USB_DEVICE_ID_LENOVO_X1_TAB :
13801483 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1429,6 +1532,10 @@ static const struct hid_device_id lenovo_devices[] = {
14291532 USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB ) },
14301533 { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
14311534 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 ) },
14321539 { }
14331540};
14341541
0 commit comments