Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HID: asus: Fix mute and touchpad-toggle keys on Medion Akoya E1239T

The mute key, is broken. All the consumer keys on the keyboard USB
interface work normally, except for mute which only sends press events
and never sends release events.

The touchpad key sends the otherwise unused input report with a report-id
of 5 on the touchpad interface. It too only sends press events. This also
requires extra special handling since the multi-touch touchpad events and
the KEY_F21 events for the touchpad toggle must not be send from the same
input_dev (userspace cannot handle this).

This commit adds special handlig for both, fixing these keys not working.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>

authored by

Hans de Goede and committed by
Jiri Kosina
350bd245 e271f6c2

+60
+60
drivers/hid/hid-asus.c
··· 42 42 #define T100_TPAD_INTF 2 43 43 #define MEDION_E1239T_TPAD_INTF 1 44 44 45 + #define E1239T_TP_TOGGLE_REPORT_ID 0x05 45 46 #define T100CHI_MOUSE_REPORT_ID 0x06 46 47 #define FEATURE_REPORT_ID 0x0d 47 48 #define INPUT_REPORT_ID 0x5d ··· 112 111 unsigned long quirks; 113 112 struct hid_device *hdev; 114 113 struct input_dev *input; 114 + struct input_dev *tp_kbd_input; 115 115 struct asus_kbd_leds *kbd_backlight; 116 116 const struct asus_touchpad_info *tp; 117 117 bool enable_backlight; ··· 277 275 return 1; 278 276 } 279 277 278 + static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size) 279 + { 280 + if (size != 3) 281 + return 0; 282 + 283 + /* Handle broken mute key which only sends press events */ 284 + if (!drvdat->tp && 285 + data[0] == 0x02 && data[1] == 0xe2 && data[2] == 0x00) { 286 + input_report_key(drvdat->input, KEY_MUTE, 1); 287 + input_sync(drvdat->input); 288 + input_report_key(drvdat->input, KEY_MUTE, 0); 289 + input_sync(drvdat->input); 290 + return 1; 291 + } 292 + 293 + /* Handle custom touchpad toggle key which only sends press events */ 294 + if (drvdat->tp_kbd_input && 295 + data[0] == 0x05 && data[1] == 0x02 && data[2] == 0x28) { 296 + input_report_key(drvdat->tp_kbd_input, KEY_F21, 1); 297 + input_sync(drvdat->tp_kbd_input); 298 + input_report_key(drvdat->tp_kbd_input, KEY_F21, 0); 299 + input_sync(drvdat->tp_kbd_input); 300 + return 1; 301 + } 302 + 303 + return 0; 304 + } 305 + 280 306 static int asus_event(struct hid_device *hdev, struct hid_field *field, 281 307 struct hid_usage *usage, __s32 value) 282 308 { ··· 328 298 329 299 if (drvdata->tp && data[0] == INPUT_REPORT_ID) 330 300 return asus_report_input(drvdata, data, size); 301 + 302 + if (drvdata->quirks & QUIRK_MEDION_E1239T) 303 + return asus_e1239t_event(drvdata, data, size); 331 304 332 305 return 0; 333 306 } ··· 666 633 hi->report->id != T100CHI_MOUSE_REPORT_ID) 667 634 return 0; 668 635 636 + /* Handle MULTI_INPUT on E1239T mouse/touchpad USB interface */ 637 + if (drvdata->tp && (drvdata->quirks & QUIRK_MEDION_E1239T)) { 638 + switch (hi->report->id) { 639 + case E1239T_TP_TOGGLE_REPORT_ID: 640 + input_set_capability(input, EV_KEY, KEY_F21); 641 + input->name = "Asus Touchpad Keys"; 642 + drvdata->tp_kbd_input = input; 643 + return 0; 644 + case INPUT_REPORT_ID: 645 + break; /* Touchpad report, handled below */ 646 + default: 647 + return 0; /* Ignore other reports */ 648 + } 649 + } 650 + 669 651 if (drvdata->tp) { 670 652 int ret; 671 653 ··· 841 793 } 842 794 } 843 795 796 + /* 797 + * The mute button is broken and only sends press events, we 798 + * deal with this in our raw_event handler, so do not map it. 799 + */ 800 + if ((drvdata->quirks & QUIRK_MEDION_E1239T) && 801 + usage->hid == (HID_UP_CONSUMER | 0xe2)) { 802 + input_set_capability(hi->input, EV_KEY, KEY_MUTE); 803 + return -1; 804 + } 805 + 844 806 return 0; 845 807 } 846 808 ··· 953 895 to_usb_interface(hdev->dev.parent)->altsetting; 954 896 955 897 if (alt->desc.bInterfaceNumber == MEDION_E1239T_TPAD_INTF) { 898 + /* For separate input-devs for tp and tp toggle key */ 899 + hdev->quirks |= HID_QUIRK_MULTI_INPUT; 956 900 drvdata->quirks |= QUIRK_SKIP_INPUT_MAPPING; 957 901 drvdata->tp = &medion_e1239t_tp; 958 902 }