2323/*
2424 */
2525
26+ #include <linux/acpi.h>
2627#include <linux/dmi.h>
2728#include <linux/hid.h>
2829#include <linux/module.h>
@@ -56,6 +57,16 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
5657#define ROG_ALLY_X_MIN_MCU 313
5758#define ROG_ALLY_MIN_MCU 319
5859
60+ /* Spurious HID codes sent by QUIRK_ROG_NKEY_KEYBOARD devices */
61+ #define ASUS_SPURIOUS_CODE_0XEA 0xea
62+ #define ASUS_SPURIOUS_CODE_0XEC 0xec
63+ #define ASUS_SPURIOUS_CODE_0X02 0x02
64+ #define ASUS_SPURIOUS_CODE_0X8A 0x8a
65+ #define ASUS_SPURIOUS_CODE_0X9E 0x9e
66+
67+ /* Special key codes */
68+ #define ASUS_FAN_CTRL_KEY_CODE 0xae
69+
5970#define SUPPORT_KBD_BACKLIGHT BIT(0)
6071
6172#define MAX_TOUCH_MAJOR 8
@@ -89,6 +100,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
89100#define QUIRK_ROG_NKEY_KEYBOARD BIT(11)
90101#define QUIRK_ROG_CLAYMORE_II_KEYBOARD BIT(12)
91102#define QUIRK_ROG_ALLY_XPAD BIT(13)
103+ #define QUIRK_HID_FN_LOCK BIT(14)
92104
93105#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
94106 QUIRK_NO_INIT_REPORTS | \
@@ -132,6 +144,8 @@ struct asus_drvdata {
132144 int battery_stat ;
133145 bool battery_in_query ;
134146 unsigned long battery_next_query ;
147+ struct work_struct fn_lock_sync_work ;
148+ bool fn_lock ;
135149};
136150
137151static int asus_report_battery (struct asus_drvdata * , u8 * , int );
@@ -313,16 +327,47 @@ static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
313327 return 0 ;
314328}
315329
330+ /*
331+ * Send events to asus-wmi driver for handling special keys
332+ */
333+ static int asus_wmi_send_event (struct asus_drvdata * drvdata , u8 code )
334+ {
335+ int err ;
336+ u32 retval ;
337+
338+ err = asus_wmi_evaluate_method (ASUS_WMI_METHODID_DEVS ,
339+ ASUS_WMI_METHODID_NOTIF , code , & retval );
340+ if (err ) {
341+ pr_warn ("Failed to notify asus-wmi: %d\n" , err );
342+ return err ;
343+ }
344+
345+ if (retval != 0 ) {
346+ pr_warn ("Failed to notify asus-wmi (retval): 0x%x\n" , retval );
347+ return - EIO ;
348+ }
349+
350+ return 0 ;
351+ }
352+
316353static int asus_event (struct hid_device * hdev , struct hid_field * field ,
317354 struct hid_usage * usage , __s32 value )
318355{
319- if ((usage -> hid & HID_USAGE_PAGE ) == 0xff310000 &&
356+ struct asus_drvdata * drvdata = hid_get_drvdata (hdev );
357+
358+ if ((usage -> hid & HID_USAGE_PAGE ) == HID_UP_ASUSVENDOR &&
320359 (usage -> hid & HID_USAGE ) != 0x00 &&
321360 (usage -> hid & HID_USAGE ) != 0xff && !usage -> type ) {
322361 hid_warn (hdev , "Unmapped Asus vendor usagepage code 0x%02x\n" ,
323362 usage -> hid & HID_USAGE );
324363 }
325364
365+ if (drvdata -> quirks & QUIRK_HID_FN_LOCK &&
366+ usage -> type == EV_KEY && usage -> code == KEY_FN_ESC && value == 1 ) {
367+ drvdata -> fn_lock = !drvdata -> fn_lock ;
368+ schedule_work (& drvdata -> fn_lock_sync_work );
369+ }
370+
326371 return 0 ;
327372}
328373
@@ -347,6 +392,43 @@ static int asus_raw_event(struct hid_device *hdev,
347392 if (report -> id == FEATURE_KBD_LED_REPORT_ID1 || report -> id == FEATURE_KBD_LED_REPORT_ID2 )
348393 return -1 ;
349394 if (drvdata -> quirks & QUIRK_ROG_NKEY_KEYBOARD ) {
395+ if (report -> id == FEATURE_KBD_REPORT_ID ) {
396+ /*
397+ * Fn+F5 fan control key - try to send WMI event to toggle fan mode.
398+ * If successful, block the event from reaching userspace.
399+ * If asus-wmi is unavailable or the call fails, let the event
400+ * pass to userspace so it can implement its own fan control.
401+ */
402+ if (data [1 ] == ASUS_FAN_CTRL_KEY_CODE ) {
403+ int ret = asus_wmi_send_event (drvdata , ASUS_FAN_CTRL_KEY_CODE );
404+
405+ if (ret == 0 ) {
406+ /* Successfully handled by asus-wmi, block event */
407+ return -1 ;
408+ }
409+
410+ /*
411+ * Warn if asus-wmi failed (but not if it's unavailable).
412+ * Let the event reach userspace in all failure cases.
413+ */
414+ if (ret != - ENODEV )
415+ hid_warn (hdev , "Failed to notify asus-wmi: %d\n" , ret );
416+ }
417+
418+ /*
419+ * ASUS ROG laptops send these codes during normal operation
420+ * with no discernable reason. Filter them out to avoid
421+ * unmapped warning messages.
422+ */
423+ if (data [1 ] == ASUS_SPURIOUS_CODE_0XEA ||
424+ data [1 ] == ASUS_SPURIOUS_CODE_0XEC ||
425+ data [1 ] == ASUS_SPURIOUS_CODE_0X02 ||
426+ data [1 ] == ASUS_SPURIOUS_CODE_0X8A ||
427+ data [1 ] == ASUS_SPURIOUS_CODE_0X9E ) {
428+ return -1 ;
429+ }
430+ }
431+
350432 /*
351433 * G713 and G733 send these codes on some keypresses, depending on
352434 * the key pressed it can trigger a shutdown event if not caught.
@@ -457,6 +539,21 @@ static int asus_kbd_disable_oobe(struct hid_device *hdev)
457539 return 0 ;
458540}
459541
542+ static int asus_kbd_set_fn_lock (struct hid_device * hdev , bool enabled )
543+ {
544+ u8 buf [] = { FEATURE_KBD_REPORT_ID , 0xd0 , 0x4e , !!enabled };
545+
546+ return asus_kbd_set_report (hdev , buf , sizeof (buf ));
547+ }
548+
549+ static void asus_sync_fn_lock (struct work_struct * work )
550+ {
551+ struct asus_drvdata * drvdata =
552+ container_of (work , struct asus_drvdata , fn_lock_sync_work );
553+
554+ asus_kbd_set_fn_lock (drvdata -> hdev , drvdata -> fn_lock );
555+ }
556+
460557static void asus_schedule_work (struct asus_kbd_leds * led )
461558{
462559 unsigned long flags ;
@@ -928,6 +1025,12 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
9281025 asus_kbd_register_leds (hdev ))
9291026 hid_warn (hdev , "Failed to initialize backlight.\n" );
9301027
1028+ if (drvdata -> quirks & QUIRK_HID_FN_LOCK ) {
1029+ drvdata -> fn_lock = true;
1030+ INIT_WORK (& drvdata -> fn_lock_sync_work , asus_sync_fn_lock );
1031+ asus_kbd_set_fn_lock (hdev , true);
1032+ }
1033+
9311034 return 0 ;
9321035}
9331036
@@ -1259,6 +1362,9 @@ static void asus_remove(struct hid_device *hdev)
12591362 cancel_work_sync (& drvdata -> kbd_backlight -> work );
12601363 }
12611364
1365+ if (drvdata -> quirks & QUIRK_HID_FN_LOCK )
1366+ cancel_work_sync (& drvdata -> fn_lock_sync_work );
1367+
12621368 hid_hw_stop (hdev );
12631369}
12641370
@@ -1386,7 +1492,7 @@ static const struct hid_device_id asus_devices[] = {
13861492 QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
13871493 { HID_USB_DEVICE (USB_VENDOR_ID_ASUSTEK ,
13881494 USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 ),
1389- QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
1495+ QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD | QUIRK_HID_FN_LOCK },
13901496 { HID_USB_DEVICE (USB_VENDOR_ID_ASUSTEK ,
13911497 USB_DEVICE_ID_ASUSTEK_ROG_Z13_LIGHTBAR ),
13921498 QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD },
0 commit comments