32
32
#include <linux/platform_data/x86/asus-wmi.h>
33
33
#include <linux/input/mt.h>
34
34
#include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
35
+ #include <linux/power_supply.h>
35
36
36
37
#include "hid-ids.h"
37
38
@@ -61,6 +62,13 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
61
62
#define CONTACT_TOUCH_MAJOR_MASK 0x07
62
63
#define CONTACT_PRESSURE_MASK 0x7f
63
64
65
+ #define BATTERY_REPORT_ID (0x03)
66
+ #define BATTERY_REPORT_SIZE (1 + 8)
67
+ #define BATTERY_LEVEL_MAX ((u8)255)
68
+ #define BATTERY_STAT_DISCONNECT (0)
69
+ #define BATTERY_STAT_CHARGING (1)
70
+ #define BATTERY_STAT_FULL (2)
71
+
64
72
#define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
65
73
#define QUIRK_NO_INIT_REPORTS BIT(1)
66
74
#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
@@ -71,6 +79,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
71
79
#define QUIRK_T100CHI BIT(7)
72
80
#define QUIRK_G752_KEYBOARD BIT(8)
73
81
#define QUIRK_T101HA_DOCK BIT(9)
82
+ #define QUIRK_T90CHI BIT(10)
74
83
75
84
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
76
85
QUIRK_NO_INIT_REPORTS | \
@@ -100,12 +109,21 @@ struct asus_touchpad_info {
100
109
101
110
struct asus_drvdata {
102
111
unsigned long quirks ;
112
+ struct hid_device * hdev ;
103
113
struct input_dev * input ;
104
114
struct asus_kbd_leds * kbd_backlight ;
105
115
const struct asus_touchpad_info * tp ;
106
116
bool enable_backlight ;
117
+ struct power_supply * battery ;
118
+ struct power_supply_desc battery_desc ;
119
+ int battery_capacity ;
120
+ int battery_stat ;
121
+ bool battery_in_query ;
122
+ unsigned long battery_next_query ;
107
123
};
108
124
125
+ static int asus_report_battery (struct asus_drvdata * , u8 * , int );
126
+
109
127
static const struct asus_touchpad_info asus_i2c_tp = {
110
128
.max_x = 2794 ,
111
129
.max_y = 1758 ,
@@ -259,6 +277,9 @@ static int asus_raw_event(struct hid_device *hdev,
259
277
{
260
278
struct asus_drvdata * drvdata = hid_get_drvdata (hdev );
261
279
280
+ if (drvdata -> battery && data [0 ] == BATTERY_REPORT_ID )
281
+ return asus_report_battery (drvdata , data , size );
282
+
262
283
if (drvdata -> tp && data [0 ] == INPUT_REPORT_ID )
263
284
return asus_report_input (drvdata , data , size );
264
285
@@ -428,6 +449,164 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
428
449
return ret ;
429
450
}
430
451
452
+ /*
453
+ * [0] REPORT_ID (same value defined in report descriptor)
454
+ * [1] rest battery level. range [0..255]
455
+ * [2]..[7] Bluetooth hardware address (MAC address)
456
+ * [8] charging status
457
+ * = 0 : AC offline / discharging
458
+ * = 1 : AC online / charging
459
+ * = 2 : AC online / fully charged
460
+ */
461
+ static int asus_parse_battery (struct asus_drvdata * drvdata , u8 * data , int size )
462
+ {
463
+ u8 sts ;
464
+ u8 lvl ;
465
+ int val ;
466
+
467
+ lvl = data [1 ];
468
+ sts = data [8 ];
469
+
470
+ drvdata -> battery_capacity = ((int )lvl * 100 ) / (int )BATTERY_LEVEL_MAX ;
471
+
472
+ switch (sts ) {
473
+ case BATTERY_STAT_CHARGING :
474
+ val = POWER_SUPPLY_STATUS_CHARGING ;
475
+ break ;
476
+ case BATTERY_STAT_FULL :
477
+ val = POWER_SUPPLY_STATUS_FULL ;
478
+ break ;
479
+ case BATTERY_STAT_DISCONNECT :
480
+ default :
481
+ val = POWER_SUPPLY_STATUS_DISCHARGING ;
482
+ break ;
483
+ }
484
+ drvdata -> battery_stat = val ;
485
+
486
+ return 0 ;
487
+ }
488
+
489
+ static int asus_report_battery (struct asus_drvdata * drvdata , u8 * data , int size )
490
+ {
491
+ /* notify only the autonomous event by device */
492
+ if ((drvdata -> battery_in_query == false) &&
493
+ (size == BATTERY_REPORT_SIZE ))
494
+ power_supply_changed (drvdata -> battery );
495
+
496
+ return 0 ;
497
+ }
498
+
499
+ static int asus_battery_query (struct asus_drvdata * drvdata )
500
+ {
501
+ u8 * buf ;
502
+ int ret = 0 ;
503
+
504
+ buf = kmalloc (BATTERY_REPORT_SIZE , GFP_KERNEL );
505
+ if (!buf )
506
+ return - ENOMEM ;
507
+
508
+ drvdata -> battery_in_query = true;
509
+ ret = hid_hw_raw_request (drvdata -> hdev , BATTERY_REPORT_ID ,
510
+ buf , BATTERY_REPORT_SIZE ,
511
+ HID_INPUT_REPORT , HID_REQ_GET_REPORT );
512
+ drvdata -> battery_in_query = false;
513
+ if (ret == BATTERY_REPORT_SIZE )
514
+ ret = asus_parse_battery (drvdata , buf , BATTERY_REPORT_SIZE );
515
+ else
516
+ ret = - ENODATA ;
517
+
518
+ kfree (buf );
519
+
520
+ return ret ;
521
+ }
522
+
523
+ static enum power_supply_property asus_battery_props [] = {
524
+ POWER_SUPPLY_PROP_STATUS ,
525
+ POWER_SUPPLY_PROP_PRESENT ,
526
+ POWER_SUPPLY_PROP_CAPACITY ,
527
+ POWER_SUPPLY_PROP_SCOPE ,
528
+ POWER_SUPPLY_PROP_MODEL_NAME ,
529
+ };
530
+
531
+ #define QUERY_MIN_INTERVAL (60 * HZ) /* 60[sec] */
532
+
533
+ static int asus_battery_get_property (struct power_supply * psy ,
534
+ enum power_supply_property psp ,
535
+ union power_supply_propval * val )
536
+ {
537
+ struct asus_drvdata * drvdata = power_supply_get_drvdata (psy );
538
+ int ret = 0 ;
539
+
540
+ switch (psp ) {
541
+ case POWER_SUPPLY_PROP_STATUS :
542
+ case POWER_SUPPLY_PROP_CAPACITY :
543
+ if (time_before (drvdata -> battery_next_query , jiffies )) {
544
+ drvdata -> battery_next_query =
545
+ jiffies + QUERY_MIN_INTERVAL ;
546
+ ret = asus_battery_query (drvdata );
547
+ if (ret )
548
+ return ret ;
549
+ }
550
+ if (psp == POWER_SUPPLY_PROP_STATUS )
551
+ val -> intval = drvdata -> battery_stat ;
552
+ else
553
+ val -> intval = drvdata -> battery_capacity ;
554
+ break ;
555
+ case POWER_SUPPLY_PROP_PRESENT :
556
+ val -> intval = 1 ;
557
+ break ;
558
+ case POWER_SUPPLY_PROP_SCOPE :
559
+ val -> intval = POWER_SUPPLY_SCOPE_DEVICE ;
560
+ break ;
561
+ case POWER_SUPPLY_PROP_MODEL_NAME :
562
+ val -> strval = drvdata -> hdev -> name ;
563
+ break ;
564
+ default :
565
+ ret = - EINVAL ;
566
+ break ;
567
+ }
568
+
569
+ return ret ;
570
+ }
571
+
572
+ static int asus_battery_probe (struct hid_device * hdev )
573
+ {
574
+ struct asus_drvdata * drvdata = hid_get_drvdata (hdev );
575
+ struct power_supply_config pscfg = { .drv_data = drvdata };
576
+ int ret = 0 ;
577
+
578
+ drvdata -> battery_capacity = 0 ;
579
+ drvdata -> battery_stat = POWER_SUPPLY_STATUS_UNKNOWN ;
580
+ drvdata -> battery_in_query = false;
581
+
582
+ drvdata -> battery_desc .properties = asus_battery_props ;
583
+ drvdata -> battery_desc .num_properties = ARRAY_SIZE (asus_battery_props );
584
+ drvdata -> battery_desc .get_property = asus_battery_get_property ;
585
+ drvdata -> battery_desc .type = POWER_SUPPLY_TYPE_BATTERY ;
586
+ drvdata -> battery_desc .use_for_apm = 0 ;
587
+ drvdata -> battery_desc .name = devm_kasprintf (& hdev -> dev , GFP_KERNEL ,
588
+ "asus-keyboard-%s-battery" ,
589
+ strlen (hdev -> uniq ) ?
590
+ hdev -> uniq : dev_name (& hdev -> dev ));
591
+ if (!drvdata -> battery_desc .name )
592
+ return - ENOMEM ;
593
+
594
+ drvdata -> battery_next_query = jiffies ;
595
+
596
+ drvdata -> battery = devm_power_supply_register (& hdev -> dev ,
597
+ & (drvdata -> battery_desc ), & pscfg );
598
+ if (IS_ERR (drvdata -> battery )) {
599
+ ret = PTR_ERR (drvdata -> battery );
600
+ drvdata -> battery = NULL ;
601
+ hid_err (hdev , "Unable to register battery device\n" );
602
+ return ret ;
603
+ }
604
+
605
+ power_supply_powers (drvdata -> battery , & hdev -> dev );
606
+
607
+ return ret ;
608
+ }
609
+
431
610
static int asus_input_configured (struct hid_device * hdev , struct hid_input * hi )
432
611
{
433
612
struct input_dev * input = hi -> input ;
@@ -500,7 +679,7 @@ static int asus_input_mapping(struct hid_device *hdev,
500
679
* This avoids a bunch of non-functional hid_input devices getting
501
680
* created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
502
681
*/
503
- if (drvdata -> quirks & QUIRK_T100CHI ) {
682
+ if (drvdata -> quirks & ( QUIRK_T100CHI | QUIRK_T90CHI ) ) {
504
683
if (field -> application == (HID_UP_GENDESK | 0x0080 ) ||
505
684
usage -> hid == (HID_UP_GENDEVCTRLS | 0x0024 ) ||
506
685
usage -> hid == (HID_UP_GENDEVCTRLS | 0x0025 ) ||
@@ -660,6 +839,15 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
660
839
661
840
drvdata -> quirks = id -> driver_data ;
662
841
842
+ /*
843
+ * T90CHI's keyboard dock returns same ID values as T100CHI's dock.
844
+ * Thus, identify T90CHI dock with product name string.
845
+ */
846
+ if (strstr (hdev -> name , "T90CHI" )) {
847
+ drvdata -> quirks &= ~QUIRK_T100CHI ;
848
+ drvdata -> quirks |= QUIRK_T90CHI ;
849
+ }
850
+
663
851
if (drvdata -> quirks & QUIRK_IS_MULTITOUCH )
664
852
drvdata -> tp = & asus_i2c_tp ;
665
853
@@ -694,6 +882,17 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
694
882
if (drvdata -> quirks & QUIRK_NO_INIT_REPORTS )
695
883
hdev -> quirks |= HID_QUIRK_NO_INIT_REPORTS ;
696
884
885
+ drvdata -> hdev = hdev ;
886
+
887
+ if (drvdata -> quirks & (QUIRK_T100CHI | QUIRK_T90CHI )) {
888
+ ret = asus_battery_probe (hdev );
889
+ if (ret ) {
890
+ hid_err (hdev ,
891
+ "Asus hid battery_probe failed: %d\n" , ret );
892
+ return ret ;
893
+ }
894
+ }
895
+
697
896
ret = hid_parse (hdev );
698
897
if (ret ) {
699
898
hid_err (hdev , "Asus hid parse failed: %d\n" , ret );
@@ -769,28 +968,44 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
769
968
hid_info (hdev , "Fixing up Asus T100 keyb report descriptor\n" );
770
969
rdesc [74 ] &= ~HID_MAIN_ITEM_CONSTANT ;
771
970
}
772
- /* For the T100CHI keyboard dock */
773
- if (drvdata -> quirks & QUIRK_T100CHI &&
774
- * rsize == 403 && rdesc [388 ] == 0x09 && rdesc [389 ] == 0x76 ) {
971
+ /* For the T100CHI/T90CHI keyboard dock */
972
+ if (drvdata -> quirks & (QUIRK_T100CHI | QUIRK_T90CHI )) {
973
+ int rsize_orig ;
974
+ int offs ;
975
+
976
+ if (drvdata -> quirks & QUIRK_T100CHI ) {
977
+ rsize_orig = 403 ;
978
+ offs = 388 ;
979
+ } else {
980
+ rsize_orig = 306 ;
981
+ offs = 291 ;
982
+ }
983
+
775
984
/*
776
985
* Change Usage (76h) to Usage Minimum (00h), Usage Maximum
777
986
* (FFh) and clear the flags in the Input() byte.
778
987
* Note the descriptor has a bogus 0 byte at the end so we
779
988
* only need 1 extra byte.
780
989
*/
781
- * rsize = 404 ;
782
- rdesc = kmemdup (rdesc , * rsize , GFP_KERNEL );
783
- if (!rdesc )
784
- return NULL ;
785
-
786
- hid_info (hdev , "Fixing up T100CHI keyb report descriptor\n" );
787
- memmove (rdesc + 392 , rdesc + 390 , 12 );
788
- rdesc [388 ] = 0x19 ;
789
- rdesc [389 ] = 0x00 ;
790
- rdesc [390 ] = 0x29 ;
791
- rdesc [391 ] = 0xff ;
792
- rdesc [402 ] = 0x00 ;
990
+ if (* rsize == rsize_orig &&
991
+ rdesc [offs ] == 0x09 && rdesc [offs + 1 ] == 0x76 ) {
992
+ * rsize = rsize_orig + 1 ;
993
+ rdesc = kmemdup (rdesc , * rsize , GFP_KERNEL );
994
+ if (!rdesc )
995
+ return NULL ;
996
+
997
+ hid_info (hdev , "Fixing up %s keyb report descriptor\n" ,
998
+ drvdata -> quirks & QUIRK_T100CHI ?
999
+ "T100CHI" : "T90CHI" );
1000
+ memmove (rdesc + offs + 4 , rdesc + offs + 2 , 12 );
1001
+ rdesc [offs ] = 0x19 ;
1002
+ rdesc [offs + 1 ] = 0x00 ;
1003
+ rdesc [offs + 2 ] = 0x29 ;
1004
+ rdesc [offs + 3 ] = 0xff ;
1005
+ rdesc [offs + 14 ] = 0x00 ;
1006
+ }
793
1007
}
1008
+
794
1009
if (drvdata -> quirks & QUIRK_G752_KEYBOARD &&
795
1010
* rsize == 75 && rdesc [61 ] == 0x15 && rdesc [62 ] == 0x00 ) {
796
1011
/* report is missing usage mninum and maximum */
0 commit comments