hc
2023-12-06 08f87f769b595151be1afeff53e144f543faa614
kernel/drivers/hid/hid-asus.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * HID driver for Asus notebook built-in keyboard.
34 * Fixes small logical maximum to match usage maximum.
....@@ -20,17 +21,15 @@
2021 */
2122
2223 /*
23
- * This program is free software; you can redistribute it and/or modify it
24
- * under the terms of the GNU General Public License as published by the Free
25
- * Software Foundation; either version 2 of the License, or (at your option)
26
- * any later version.
2724 */
2825
2926 #include <linux/dmi.h>
3027 #include <linux/hid.h>
3128 #include <linux/module.h>
29
+#include <linux/platform_data/x86/asus-wmi.h>
3230 #include <linux/input/mt.h>
3331 #include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
32
+#include <linux/power_supply.h>
3433
3534 #include "hid-ids.h"
3635
....@@ -41,7 +40,9 @@
4140 MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
4241
4342 #define T100_TPAD_INTF 2
43
+#define MEDION_E1239T_TPAD_INTF 1
4444
45
+#define E1239T_TP_TOGGLE_REPORT_ID 0x05
4546 #define T100CHI_MOUSE_REPORT_ID 0x06
4647 #define FEATURE_REPORT_ID 0x0d
4748 #define INPUT_REPORT_ID 0x5d
....@@ -60,6 +61,13 @@
6061 #define CONTACT_TOUCH_MAJOR_MASK 0x07
6162 #define CONTACT_PRESSURE_MASK 0x7f
6263
64
+#define BATTERY_REPORT_ID (0x03)
65
+#define BATTERY_REPORT_SIZE (1 + 8)
66
+#define BATTERY_LEVEL_MAX ((u8)255)
67
+#define BATTERY_STAT_DISCONNECT (0)
68
+#define BATTERY_STAT_CHARGING (1)
69
+#define BATTERY_STAT_FULL (2)
70
+
6371 #define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
6472 #define QUIRK_NO_INIT_REPORTS BIT(1)
6573 #define QUIRK_SKIP_INPUT_MAPPING BIT(2)
....@@ -69,6 +77,9 @@
6977 #define QUIRK_T100_KEYBOARD BIT(6)
7078 #define QUIRK_T100CHI BIT(7)
7179 #define QUIRK_G752_KEYBOARD BIT(8)
80
+#define QUIRK_T101HA_DOCK BIT(9)
81
+#define QUIRK_T90CHI BIT(10)
82
+#define QUIRK_MEDION_E1239T BIT(11)
7283
7384 #define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
7485 QUIRK_NO_INIT_REPORTS | \
....@@ -94,21 +105,33 @@
94105 int res_y;
95106 int contact_size;
96107 int max_contacts;
108
+ int report_size;
97109 };
98110
99111 struct asus_drvdata {
100112 unsigned long quirks;
113
+ struct hid_device *hdev;
101114 struct input_dev *input;
115
+ struct input_dev *tp_kbd_input;
102116 struct asus_kbd_leds *kbd_backlight;
103117 const struct asus_touchpad_info *tp;
104118 bool enable_backlight;
119
+ struct power_supply *battery;
120
+ struct power_supply_desc battery_desc;
121
+ int battery_capacity;
122
+ int battery_stat;
123
+ bool battery_in_query;
124
+ unsigned long battery_next_query;
105125 };
126
+
127
+static int asus_report_battery(struct asus_drvdata *, u8 *, int);
106128
107129 static const struct asus_touchpad_info asus_i2c_tp = {
108130 .max_x = 2794,
109131 .max_y = 1758,
110132 .contact_size = 5,
111133 .max_contacts = 5,
134
+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
112135 };
113136
114137 static const struct asus_touchpad_info asus_t100ta_tp = {
....@@ -118,6 +141,7 @@
118141 .res_y = 27, /* units/mm */
119142 .contact_size = 5,
120143 .max_contacts = 5,
144
+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
121145 };
122146
123147 static const struct asus_touchpad_info asus_t100ha_tp = {
....@@ -127,6 +151,7 @@
127151 .res_y = 29, /* units/mm */
128152 .contact_size = 5,
129153 .max_contacts = 5,
154
+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
130155 };
131156
132157 static const struct asus_touchpad_info asus_t200ta_tp = {
....@@ -136,6 +161,7 @@
136161 .res_y = 28, /* units/mm */
137162 .contact_size = 5,
138163 .max_contacts = 5,
164
+ .report_size = 28 /* 2 byte header + 5 * 5 + 1 byte footer */,
139165 };
140166
141167 static const struct asus_touchpad_info asus_t100chi_tp = {
....@@ -145,6 +171,17 @@
145171 .res_y = 29, /* units/mm */
146172 .contact_size = 3,
147173 .max_contacts = 4,
174
+ .report_size = 15 /* 2 byte header + 3 * 4 + 1 byte footer */,
175
+};
176
+
177
+static const struct asus_touchpad_info medion_e1239t_tp = {
178
+ .max_x = 2640,
179
+ .max_y = 1380,
180
+ .res_x = 29, /* units/mm */
181
+ .res_y = 28, /* units/mm */
182
+ .contact_size = 5,
183
+ .max_contacts = 5,
184
+ .report_size = 32 /* 2 byte header + 5 * 5 + 5 byte footer */,
148185 };
149186
150187 static void asus_report_contact_down(struct asus_drvdata *drvdat,
....@@ -212,7 +249,7 @@
212249 int i, toolType = MT_TOOL_FINGER;
213250 u8 *contactData = data + 2;
214251
215
- if (size != 3 + drvdat->tp->contact_size * drvdat->tp->max_contacts)
252
+ if (size != drvdat->tp->report_size)
216253 return 0;
217254
218255 for (i = 0; i < drvdat->tp->max_contacts; i++) {
....@@ -240,13 +277,60 @@
240277 return 1;
241278 }
242279
280
+static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
281
+{
282
+ if (size != 3)
283
+ return 0;
284
+
285
+ /* Handle broken mute key which only sends press events */
286
+ if (!drvdat->tp &&
287
+ data[0] == 0x02 && data[1] == 0xe2 && data[2] == 0x00) {
288
+ input_report_key(drvdat->input, KEY_MUTE, 1);
289
+ input_sync(drvdat->input);
290
+ input_report_key(drvdat->input, KEY_MUTE, 0);
291
+ input_sync(drvdat->input);
292
+ return 1;
293
+ }
294
+
295
+ /* Handle custom touchpad toggle key which only sends press events */
296
+ if (drvdat->tp_kbd_input &&
297
+ data[0] == 0x05 && data[1] == 0x02 && data[2] == 0x28) {
298
+ input_report_key(drvdat->tp_kbd_input, KEY_F21, 1);
299
+ input_sync(drvdat->tp_kbd_input);
300
+ input_report_key(drvdat->tp_kbd_input, KEY_F21, 0);
301
+ input_sync(drvdat->tp_kbd_input);
302
+ return 1;
303
+ }
304
+
305
+ return 0;
306
+}
307
+
308
+static int asus_event(struct hid_device *hdev, struct hid_field *field,
309
+ struct hid_usage *usage, __s32 value)
310
+{
311
+ if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
312
+ (usage->hid & HID_USAGE) != 0x00 &&
313
+ (usage->hid & HID_USAGE) != 0xff && !usage->type) {
314
+ hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
315
+ usage->hid & HID_USAGE);
316
+ }
317
+
318
+ return 0;
319
+}
320
+
243321 static int asus_raw_event(struct hid_device *hdev,
244322 struct hid_report *report, u8 *data, int size)
245323 {
246324 struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
247325
326
+ if (drvdata->battery && data[0] == BATTERY_REPORT_ID)
327
+ return asus_report_battery(drvdata, data, size);
328
+
248329 if (drvdata->tp && data[0] == INPUT_REPORT_ID)
249330 return asus_report_input(drvdata, data, size);
331
+
332
+ if (drvdata->quirks & QUIRK_MEDION_E1239T)
333
+ return asus_e1239t_event(drvdata, data, size);
250334
251335 return 0;
252336 }
....@@ -349,6 +433,27 @@
349433 hid_err(led->hdev, "Asus failed to set keyboard backlight: %d\n", ret);
350434 }
351435
436
+/* WMI-based keyboard backlight LED control (via asus-wmi driver) takes
437
+ * precedence. We only activate HID-based backlight control when the
438
+ * WMI control is not available.
439
+ */
440
+static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)
441
+{
442
+ u32 value;
443
+ int ret;
444
+
445
+ if (!IS_ENABLED(CONFIG_ASUS_WMI))
446
+ return false;
447
+
448
+ ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS,
449
+ ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);
450
+ hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value);
451
+ if (ret)
452
+ return false;
453
+
454
+ return !!(value & ASUS_WMI_DSTS_PRESENCE_BIT);
455
+}
456
+
352457 static int asus_kbd_register_leds(struct hid_device *hdev)
353458 {
354459 struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
....@@ -393,6 +498,164 @@
393498 return ret;
394499 }
395500
501
+/*
502
+ * [0] REPORT_ID (same value defined in report descriptor)
503
+ * [1] rest battery level. range [0..255]
504
+ * [2]..[7] Bluetooth hardware address (MAC address)
505
+ * [8] charging status
506
+ * = 0 : AC offline / discharging
507
+ * = 1 : AC online / charging
508
+ * = 2 : AC online / fully charged
509
+ */
510
+static int asus_parse_battery(struct asus_drvdata *drvdata, u8 *data, int size)
511
+{
512
+ u8 sts;
513
+ u8 lvl;
514
+ int val;
515
+
516
+ lvl = data[1];
517
+ sts = data[8];
518
+
519
+ drvdata->battery_capacity = ((int)lvl * 100) / (int)BATTERY_LEVEL_MAX;
520
+
521
+ switch (sts) {
522
+ case BATTERY_STAT_CHARGING:
523
+ val = POWER_SUPPLY_STATUS_CHARGING;
524
+ break;
525
+ case BATTERY_STAT_FULL:
526
+ val = POWER_SUPPLY_STATUS_FULL;
527
+ break;
528
+ case BATTERY_STAT_DISCONNECT:
529
+ default:
530
+ val = POWER_SUPPLY_STATUS_DISCHARGING;
531
+ break;
532
+ }
533
+ drvdata->battery_stat = val;
534
+
535
+ return 0;
536
+}
537
+
538
+static int asus_report_battery(struct asus_drvdata *drvdata, u8 *data, int size)
539
+{
540
+ /* notify only the autonomous event by device */
541
+ if ((drvdata->battery_in_query == false) &&
542
+ (size == BATTERY_REPORT_SIZE))
543
+ power_supply_changed(drvdata->battery);
544
+
545
+ return 0;
546
+}
547
+
548
+static int asus_battery_query(struct asus_drvdata *drvdata)
549
+{
550
+ u8 *buf;
551
+ int ret = 0;
552
+
553
+ buf = kmalloc(BATTERY_REPORT_SIZE, GFP_KERNEL);
554
+ if (!buf)
555
+ return -ENOMEM;
556
+
557
+ drvdata->battery_in_query = true;
558
+ ret = hid_hw_raw_request(drvdata->hdev, BATTERY_REPORT_ID,
559
+ buf, BATTERY_REPORT_SIZE,
560
+ HID_INPUT_REPORT, HID_REQ_GET_REPORT);
561
+ drvdata->battery_in_query = false;
562
+ if (ret == BATTERY_REPORT_SIZE)
563
+ ret = asus_parse_battery(drvdata, buf, BATTERY_REPORT_SIZE);
564
+ else
565
+ ret = -ENODATA;
566
+
567
+ kfree(buf);
568
+
569
+ return ret;
570
+}
571
+
572
+static enum power_supply_property asus_battery_props[] = {
573
+ POWER_SUPPLY_PROP_STATUS,
574
+ POWER_SUPPLY_PROP_PRESENT,
575
+ POWER_SUPPLY_PROP_CAPACITY,
576
+ POWER_SUPPLY_PROP_SCOPE,
577
+ POWER_SUPPLY_PROP_MODEL_NAME,
578
+};
579
+
580
+#define QUERY_MIN_INTERVAL (60 * HZ) /* 60[sec] */
581
+
582
+static int asus_battery_get_property(struct power_supply *psy,
583
+ enum power_supply_property psp,
584
+ union power_supply_propval *val)
585
+{
586
+ struct asus_drvdata *drvdata = power_supply_get_drvdata(psy);
587
+ int ret = 0;
588
+
589
+ switch (psp) {
590
+ case POWER_SUPPLY_PROP_STATUS:
591
+ case POWER_SUPPLY_PROP_CAPACITY:
592
+ if (time_before(drvdata->battery_next_query, jiffies)) {
593
+ drvdata->battery_next_query =
594
+ jiffies + QUERY_MIN_INTERVAL;
595
+ ret = asus_battery_query(drvdata);
596
+ if (ret)
597
+ return ret;
598
+ }
599
+ if (psp == POWER_SUPPLY_PROP_STATUS)
600
+ val->intval = drvdata->battery_stat;
601
+ else
602
+ val->intval = drvdata->battery_capacity;
603
+ break;
604
+ case POWER_SUPPLY_PROP_PRESENT:
605
+ val->intval = 1;
606
+ break;
607
+ case POWER_SUPPLY_PROP_SCOPE:
608
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
609
+ break;
610
+ case POWER_SUPPLY_PROP_MODEL_NAME:
611
+ val->strval = drvdata->hdev->name;
612
+ break;
613
+ default:
614
+ ret = -EINVAL;
615
+ break;
616
+ }
617
+
618
+ return ret;
619
+}
620
+
621
+static int asus_battery_probe(struct hid_device *hdev)
622
+{
623
+ struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
624
+ struct power_supply_config pscfg = { .drv_data = drvdata };
625
+ int ret = 0;
626
+
627
+ drvdata->battery_capacity = 0;
628
+ drvdata->battery_stat = POWER_SUPPLY_STATUS_UNKNOWN;
629
+ drvdata->battery_in_query = false;
630
+
631
+ drvdata->battery_desc.properties = asus_battery_props;
632
+ drvdata->battery_desc.num_properties = ARRAY_SIZE(asus_battery_props);
633
+ drvdata->battery_desc.get_property = asus_battery_get_property;
634
+ drvdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
635
+ drvdata->battery_desc.use_for_apm = 0;
636
+ drvdata->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL,
637
+ "asus-keyboard-%s-battery",
638
+ strlen(hdev->uniq) ?
639
+ hdev->uniq : dev_name(&hdev->dev));
640
+ if (!drvdata->battery_desc.name)
641
+ return -ENOMEM;
642
+
643
+ drvdata->battery_next_query = jiffies;
644
+
645
+ drvdata->battery = devm_power_supply_register(&hdev->dev,
646
+ &(drvdata->battery_desc), &pscfg);
647
+ if (IS_ERR(drvdata->battery)) {
648
+ ret = PTR_ERR(drvdata->battery);
649
+ drvdata->battery = NULL;
650
+ hid_err(hdev, "Unable to register battery device\n");
651
+ return ret;
652
+ }
653
+
654
+ power_supply_powers(drvdata->battery, &hdev->dev);
655
+
656
+ return ret;
657
+}
658
+
396659 static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
397660 {
398661 struct input_dev *input = hi->input;
....@@ -402,6 +665,21 @@
402665 if (drvdata->quirks & QUIRK_T100CHI &&
403666 hi->report->id != T100CHI_MOUSE_REPORT_ID)
404667 return 0;
668
+
669
+ /* Handle MULTI_INPUT on E1239T mouse/touchpad USB interface */
670
+ if (drvdata->tp && (drvdata->quirks & QUIRK_MEDION_E1239T)) {
671
+ switch (hi->report->id) {
672
+ case E1239T_TP_TOGGLE_REPORT_ID:
673
+ input_set_capability(input, EV_KEY, KEY_F21);
674
+ input->name = "Asus Touchpad Keys";
675
+ drvdata->tp_kbd_input = input;
676
+ return 0;
677
+ case INPUT_REPORT_ID:
678
+ break; /* Touchpad report, handled below */
679
+ default:
680
+ return 0; /* Ignore other reports */
681
+ }
682
+ }
405683
406684 if (drvdata->tp) {
407685 int ret;
....@@ -436,7 +714,9 @@
436714
437715 drvdata->input = input;
438716
439
- if (drvdata->enable_backlight && asus_kbd_register_leds(hdev))
717
+ if (drvdata->enable_backlight &&
718
+ !asus_kbd_wmi_led_control_present(hdev) &&
719
+ asus_kbd_register_leds(hdev))
440720 hid_warn(hdev, "Failed to initialize backlight.\n");
441721
442722 return 0;
....@@ -463,29 +743,22 @@
463743 * This avoids a bunch of non-functional hid_input devices getting
464744 * created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
465745 */
466
- if (drvdata->quirks & QUIRK_T100CHI) {
467
- if (field->application == (HID_UP_GENDESK | 0x0080) ||
468
- usage->hid == (HID_UP_GENDEVCTRLS | 0x0024) ||
469
- usage->hid == (HID_UP_GENDEVCTRLS | 0x0025) ||
470
- usage->hid == (HID_UP_GENDEVCTRLS | 0x0026))
471
- return -1;
472
- /*
473
- * We use the hid_input for the mouse report for the touchpad,
474
- * keep the left button, to avoid the core removing it.
475
- */
476
- if (field->application == HID_GD_MOUSE &&
477
- usage->hid != (HID_UP_BUTTON | 1))
478
- return -1;
479
- }
746
+ if ((drvdata->quirks & (QUIRK_T100CHI | QUIRK_T90CHI)) &&
747
+ (field->application == (HID_UP_GENDESK | 0x0080) ||
748
+ field->application == HID_GD_MOUSE ||
749
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0024) ||
750
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0025) ||
751
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0026)))
752
+ return -1;
480753
481754 /* ASUS-specific keyboard hotkeys */
482755 if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {
483
- set_bit(EV_REP, hi->input->evbit);
484756 switch (usage->hid & HID_USAGE) {
485757 case 0x10: asus_map_key_clear(KEY_BRIGHTNESSDOWN); break;
486758 case 0x20: asus_map_key_clear(KEY_BRIGHTNESSUP); break;
487759 case 0x35: asus_map_key_clear(KEY_DISPLAY_OFF); break;
488760 case 0x6c: asus_map_key_clear(KEY_SLEEP); break;
761
+ case 0x7c: asus_map_key_clear(KEY_MICMUTE); break;
489762 case 0x82: asus_map_key_clear(KEY_CAMERA); break;
490763 case 0x88: asus_map_key_clear(KEY_RFKILL); break;
491764 case 0xb5: asus_map_key_clear(KEY_CALC); break;
....@@ -504,6 +777,9 @@
504777 /* Fn+Space Power4Gear Hybrid */
505778 case 0x5c: asus_map_key_clear(KEY_PROG3); break;
506779
780
+ /* Fn+F5 "fan" symbol on FX503VD */
781
+ case 0x99: asus_map_key_clear(KEY_PROG4); break;
782
+
507783 default:
508784 /* ASUS lazily declares 256 usages, ignore the rest,
509785 * as some make the keyboard appear as a pointer device. */
....@@ -519,11 +795,11 @@
519795 if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
520796 drvdata->enable_backlight = true;
521797
798
+ set_bit(EV_REP, hi->input->evbit);
522799 return 1;
523800 }
524801
525802 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR) {
526
- set_bit(EV_REP, hi->input->evbit);
527803 switch (usage->hid & HID_USAGE) {
528804 case 0xff01: asus_map_key_clear(BTN_1); break;
529805 case 0xff02: asus_map_key_clear(BTN_2); break;
....@@ -546,6 +822,7 @@
546822 return 0;
547823 }
548824
825
+ set_bit(EV_REP, hi->input->evbit);
549826 return 1;
550827 }
551828
....@@ -562,6 +839,16 @@
562839 */
563840 return -1;
564841 }
842
+ }
843
+
844
+ /*
845
+ * The mute button is broken and only sends press events, we
846
+ * deal with this in our raw_event handler, so do not map it.
847
+ */
848
+ if ((drvdata->quirks & QUIRK_MEDION_E1239T) &&
849
+ usage->hid == (HID_UP_CONSUMER | 0xe2)) {
850
+ input_set_capability(hi->input, EV_KEY, KEY_MUTE);
851
+ return -1;
565852 }
566853
567854 return 0;
....@@ -619,6 +906,15 @@
619906
620907 drvdata->quirks = id->driver_data;
621908
909
+ /*
910
+ * T90CHI's keyboard dock returns same ID values as T100CHI's dock.
911
+ * Thus, identify T90CHI dock with product name string.
912
+ */
913
+ if (strstr(hdev->name, "T90CHI")) {
914
+ drvdata->quirks &= ~QUIRK_T100CHI;
915
+ drvdata->quirks |= QUIRK_T90CHI;
916
+ }
917
+
622918 if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
623919 drvdata->tp = &asus_i2c_tp;
624920
....@@ -650,14 +946,42 @@
650946 drvdata->tp = &asus_t100chi_tp;
651947 }
652948
949
+ if ((drvdata->quirks & QUIRK_MEDION_E1239T) && hid_is_usb(hdev)) {
950
+ struct usb_host_interface *alt =
951
+ to_usb_interface(hdev->dev.parent)->altsetting;
952
+
953
+ if (alt->desc.bInterfaceNumber == MEDION_E1239T_TPAD_INTF) {
954
+ /* For separate input-devs for tp and tp toggle key */
955
+ hdev->quirks |= HID_QUIRK_MULTI_INPUT;
956
+ drvdata->quirks |= QUIRK_SKIP_INPUT_MAPPING;
957
+ drvdata->tp = &medion_e1239t_tp;
958
+ }
959
+ }
960
+
653961 if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
654962 hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
963
+
964
+ drvdata->hdev = hdev;
965
+
966
+ if (drvdata->quirks & (QUIRK_T100CHI | QUIRK_T90CHI)) {
967
+ ret = asus_battery_probe(hdev);
968
+ if (ret) {
969
+ hid_err(hdev,
970
+ "Asus hid battery_probe failed: %d\n", ret);
971
+ return ret;
972
+ }
973
+ }
655974
656975 ret = hid_parse(hdev);
657976 if (ret) {
658977 hid_err(hdev, "Asus hid parse failed: %d\n", ret);
659978 return ret;
660979 }
980
+
981
+ /* use hid-multitouch for T101HA touchpad */
982
+ if (id->driver_data & QUIRK_T101HA_DOCK &&
983
+ hdev->collection->usage == HID_GD_MOUSE)
984
+ return -ENODEV;
661985
662986 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
663987 if (ret) {
....@@ -723,28 +1047,44 @@
7231047 hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
7241048 rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
7251049 }
726
- /* For the T100CHI keyboard dock */
727
- if (drvdata->quirks & QUIRK_T100CHI &&
728
- *rsize == 403 && rdesc[388] == 0x09 && rdesc[389] == 0x76) {
1050
+ /* For the T100CHI/T90CHI keyboard dock */
1051
+ if (drvdata->quirks & (QUIRK_T100CHI | QUIRK_T90CHI)) {
1052
+ int rsize_orig;
1053
+ int offs;
1054
+
1055
+ if (drvdata->quirks & QUIRK_T100CHI) {
1056
+ rsize_orig = 403;
1057
+ offs = 388;
1058
+ } else {
1059
+ rsize_orig = 306;
1060
+ offs = 291;
1061
+ }
1062
+
7291063 /*
7301064 * Change Usage (76h) to Usage Minimum (00h), Usage Maximum
7311065 * (FFh) and clear the flags in the Input() byte.
7321066 * Note the descriptor has a bogus 0 byte at the end so we
7331067 * only need 1 extra byte.
7341068 */
735
- *rsize = 404;
736
- rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
737
- if (!rdesc)
738
- return NULL;
1069
+ if (*rsize == rsize_orig &&
1070
+ rdesc[offs] == 0x09 && rdesc[offs + 1] == 0x76) {
1071
+ *rsize = rsize_orig + 1;
1072
+ rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
1073
+ if (!rdesc)
1074
+ return NULL;
7391075
740
- hid_info(hdev, "Fixing up T100CHI keyb report descriptor\n");
741
- memmove(rdesc + 392, rdesc + 390, 12);
742
- rdesc[388] = 0x19;
743
- rdesc[389] = 0x00;
744
- rdesc[390] = 0x29;
745
- rdesc[391] = 0xff;
746
- rdesc[402] = 0x00;
1076
+ hid_info(hdev, "Fixing up %s keyb report descriptor\n",
1077
+ drvdata->quirks & QUIRK_T100CHI ?
1078
+ "T100CHI" : "T90CHI");
1079
+ memmove(rdesc + offs + 4, rdesc + offs + 2, 12);
1080
+ rdesc[offs] = 0x19;
1081
+ rdesc[offs + 1] = 0x00;
1082
+ rdesc[offs + 2] = 0x29;
1083
+ rdesc[offs + 3] = 0xff;
1084
+ rdesc[offs + 14] = 0x00;
1085
+ }
7471086 }
1087
+
7481088 if (drvdata->quirks & QUIRK_G752_KEYBOARD &&
7491089 *rsize == 75 && rdesc[61] == 0x15 && rdesc[62] == 0x00) {
7501090 /* report is missing usage mninum and maximum */
....@@ -782,17 +1122,23 @@
7821122 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
7831123 USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3), QUIRK_G752_KEYBOARD },
7841124 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
1125
+ USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD),
1126
+ QUIRK_USE_KBD_BACKLIGHT },
1127
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
7851128 USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD),
7861129 QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
7871130 { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
7881131 USB_DEVICE_ID_ASUSTEK_T100TAF_KEYBOARD),
7891132 QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
1133
+ { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
1134
+ USB_DEVICE_ID_ASUSTEK_T101HA_KEYBOARD), QUIRK_T101HA_DOCK },
7901135 { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_ASUS_AK1D) },
7911136 { HID_USB_DEVICE(USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_ASUS_MD_5110) },
7921137 { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_ASUS_MD_5112) },
7931138 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
7941139 USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI },
795
-
1140
+ { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE_MEDION_E1239T),
1141
+ QUIRK_MEDION_E1239T },
7961142 { }
7971143 };
7981144 MODULE_DEVICE_TABLE(hid, asus_devices);
....@@ -808,6 +1154,7 @@
8081154 #ifdef CONFIG_PM
8091155 .reset_resume = asus_reset_resume,
8101156 #endif
1157
+ .event = asus_event,
8111158 .raw_event = asus_raw_event
8121159 };
8131160 module_hid_driver(asus_driver);