3131#include <linux/input.h>
3232#include <linux/leds.h>
3333#include <linux/workqueue.h>
34+ #include <linux/platform_profile.h>
3435
3536#include "hid-ids.h"
3637
3738/* Userspace expects F20 for mic-mute KEY_MICMUTE does not work */
3839#define LENOVO_KEY_MICMUTE KEY_F20
3940
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+
4048struct lenovo_drvdata {
4149 u8 led_report [3 ]; /* Must be first for proper alignment */
4250 int led_state ;
@@ -71,6 +79,14 @@ struct lenovo_drvdata {
7179#define TP10UBKBD_LED_OFF 1
7280#define TP10UBKBD_LED_ON 2
7381
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+
7490static int lenovo_led_set_tp10ubkbd (struct hid_device * hdev , u8 led_code ,
7591 enum led_brightness value )
7692{
@@ -472,6 +488,8 @@ static int lenovo_input_mapping(struct hid_device *hdev,
472488 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
473489 return lenovo_input_mapping_tp10_ultrabook_kbd (hdev , hi , field ,
474490 usage , bit , max );
491+ case USB_DEVICE_ID_LENOVO_X12_TAB :
492+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
475493 case USB_DEVICE_ID_LENOVO_X1_TAB :
476494 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
477495 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,
582600 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
583601 lenovo_features_set_cptkbd (hdev );
584602 break ;
603+ case USB_DEVICE_ID_LENOVO_X12_TAB :
604+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
585605 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
586606 case USB_DEVICE_ID_LENOVO_X1_TAB :
587607 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -680,6 +700,55 @@ static const struct attribute_group lenovo_attr_group_cptkbd = {
680700 .attrs = lenovo_attributes_cptkbd ,
681701};
682702
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+
683752static int lenovo_raw_event (struct hid_device * hdev ,
684753 struct hid_report * report , u8 * data , int size )
685754{
@@ -697,6 +766,15 @@ static int lenovo_raw_event(struct hid_device *hdev,
697766 data [2 ] = 0x01 ;
698767 }
699768
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+
700778 return 0 ;
701779}
702780
@@ -776,6 +854,8 @@ static int lenovo_event(struct hid_device *hdev, struct hid_field *field,
776854 case USB_DEVICE_ID_LENOVO_TPIIUSBKBD :
777855 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
778856 return lenovo_event_cptkbd (hdev , field , usage , value );
857+ case USB_DEVICE_ID_LENOVO_X12_TAB :
858+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
779859 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
780860 case USB_DEVICE_ID_LENOVO_X1_TAB :
781861 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1057,6 +1137,8 @@ static int lenovo_led_brightness_set(struct led_classdev *led_cdev,
10571137 case USB_DEVICE_ID_LENOVO_TPKBD :
10581138 lenovo_led_set_tpkbd (hdev );
10591139 break ;
1140+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1141+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
10601142 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
10611143 case USB_DEVICE_ID_LENOVO_X1_TAB :
10621144 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1243,8 +1325,15 @@ static int lenovo_probe_tp10ubkbd(struct hid_device *hdev)
12431325 * We cannot read the state, only set it, so we force it to on here
12441326 * (which should be a no-op) to make sure that our state matches the
12451327 * 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.
12461332 */
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+
12481337 lenovo_led_set_tp10ubkbd (hdev , TP10UBKBD_FN_LOCK_LED , data -> fn_lock );
12491338
12501339 ret = sysfs_create_group (& hdev -> dev .kobj , & lenovo_attr_group_tp10ubkbd );
@@ -1288,6 +1377,8 @@ static int lenovo_probe(struct hid_device *hdev,
12881377 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
12891378 ret = lenovo_probe_cptkbd (hdev );
12901379 break ;
1380+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1381+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
12911382 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
12921383 case USB_DEVICE_ID_LENOVO_X1_TAB :
12931384 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1375,6 +1466,8 @@ static void lenovo_remove(struct hid_device *hdev)
13751466 case USB_DEVICE_ID_LENOVO_TPIIBTKBD :
13761467 lenovo_remove_cptkbd (hdev );
13771468 break ;
1469+ case USB_DEVICE_ID_LENOVO_X12_TAB :
1470+ case USB_DEVICE_ID_LENOVO_X12_TAB2 :
13781471 case USB_DEVICE_ID_LENOVO_TP10UBKBD :
13791472 case USB_DEVICE_ID_LENOVO_X1_TAB :
13801473 case USB_DEVICE_ID_LENOVO_X1_TAB3 :
@@ -1429,6 +1522,10 @@ static const struct hid_device_id lenovo_devices[] = {
14291522 USB_VENDOR_ID_LENOVO , USB_DEVICE_ID_LENOVO_X1_TAB ) },
14301523 { HID_DEVICE (BUS_USB , HID_GROUP_GENERIC ,
14311524 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 ) },
14321529 { }
14331530};
14341531
0 commit comments