Skip to content

Commit c6400e5

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - support for Pro Pen slim, from Jason Gerecke - power management improvements to Intel-ISH driver, from Song Hongyan - UCLogic driver revamp in order to be able to support wider range of Huion tablets, from Nikolai Kondrashov - Asus Transbook support, from NOGUCHI Hiroshi - other assorted small bugfixes / cleanups and device ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (46 commits) HID: Remove Waltop tablets from hid_have_special_driver HID: Remove KYE tablets from hid_have_special_driver HID: Remove hid-uclogic entries from hid_have_special_driver HID: uclogic: Do not initialize non-USB devices HID: uclogic: Add support for Ugee G5 HID: uclogic: Support Gray-coded rotary encoders HID: uclogic: Support faking Wacom pad device ID HID: uclogic: Add support for XP-Pen Deco 01 HID: uclogic: Add support for XP-Pen Star G640 HID: uclogic: Add support for XP-Pen Star G540 HID: uclogic: Add support for Ugee EX07S frame controls HID: uclogic: Add support for Ugee M540 HID: uclogic: Add support for Ugee 2150 HID: uclogic: Support v2 protocol HID: uclogic: Support fragmented high-res reports HID: uclogic: Support in-range reporting emulation HID: uclogic: Designate current protocol v1 HID: uclogic: Re-initialize tablets on resume HID: uclogic: Extract tablet parameter discovery into a module HID: uclogic: Extract report descriptors to a module ...
2 parents b7af27b + 49374f0 commit c6400e5

35 files changed

+3049
-739
lines changed

drivers/hid/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,12 @@ config HID_WALTOP
412412
---help---
413413
Support for Waltop tablets.
414414

415+
config HID_VIEWSONIC
416+
tristate "ViewSonic/Signotec"
417+
depends on HID
418+
help
419+
Support for ViewSonic/Signotec PD1011 signature pad.
420+
415421
config HID_GYRATION
416422
tristate "Gyration remote control"
417423
depends on HID
@@ -590,6 +596,13 @@ config HID_MAGICMOUSE
590596
Say Y here if you want support for the multi-touch features of the
591597
Apple Wireless "Magic" Mouse and the Apple Wireless "Magic" Trackpad.
592598

599+
config HID_MALTRON
600+
tristate "Maltron L90 keyboard"
601+
depends on HID
602+
---help---
603+
Adds support for the volume up, volume down, mute, and play/pause buttons
604+
of the Maltron L90 keyboard.
605+
593606
config HID_MAYFLASH
594607
tristate "Mayflash game controller adapter force feedback"
595608
depends on HID

drivers/hid/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o
6666
obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o
6767
obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o
6868
obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o
69+
obj-$(CONFIG_HID_MALTRON) += hid-maltron.o
6970
obj-$(CONFIG_HID_MAYFLASH) += hid-mf.o
7071
obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o
7172
obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o
@@ -108,12 +109,16 @@ obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o
108109
obj-$(CONFIG_HID_TIVO) += hid-tivo.o
109110
obj-$(CONFIG_HID_TOPSEED) += hid-topseed.o
110111
obj-$(CONFIG_HID_TWINHAN) += hid-twinhan.o
112+
hid-uclogic-objs := hid-uclogic-core.o \
113+
hid-uclogic-rdesc.o \
114+
hid-uclogic-params.o
111115
obj-$(CONFIG_HID_UCLOGIC) += hid-uclogic.o
112116
obj-$(CONFIG_HID_UDRAW_PS3) += hid-udraw-ps3.o
113117
obj-$(CONFIG_HID_LED) += hid-led.o
114118
obj-$(CONFIG_HID_XINMO) += hid-xinmo.o
115119
obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o
116120
obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o
121+
obj-$(CONFIG_HID_VIEWSONIC) += hid-viewsonic.o
117122

118123
wacom-objs := wacom_wac.o wacom_sys.o
119124
obj-$(CONFIG_HID_WACOM) += wacom.o

drivers/hid/hid-asus.c

Lines changed: 231 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/platform_data/x86/asus-wmi.h>
3333
#include <linux/input/mt.h>
3434
#include <linux/usb.h> /* For to_usb_interface for T100 touchpad intf check */
35+
#include <linux/power_supply.h>
3536

3637
#include "hid-ids.h"
3738

@@ -61,6 +62,13 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
6162
#define CONTACT_TOUCH_MAJOR_MASK 0x07
6263
#define CONTACT_PRESSURE_MASK 0x7f
6364

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+
6472
#define QUIRK_FIX_NOTEBOOK_REPORT BIT(0)
6573
#define QUIRK_NO_INIT_REPORTS BIT(1)
6674
#define QUIRK_SKIP_INPUT_MAPPING BIT(2)
@@ -71,6 +79,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
7179
#define QUIRK_T100CHI BIT(7)
7280
#define QUIRK_G752_KEYBOARD BIT(8)
7381
#define QUIRK_T101HA_DOCK BIT(9)
82+
#define QUIRK_T90CHI BIT(10)
7483

7584
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
7685
QUIRK_NO_INIT_REPORTS | \
@@ -100,12 +109,21 @@ struct asus_touchpad_info {
100109

101110
struct asus_drvdata {
102111
unsigned long quirks;
112+
struct hid_device *hdev;
103113
struct input_dev *input;
104114
struct asus_kbd_leds *kbd_backlight;
105115
const struct asus_touchpad_info *tp;
106116
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;
107123
};
108124

125+
static int asus_report_battery(struct asus_drvdata *, u8 *, int);
126+
109127
static const struct asus_touchpad_info asus_i2c_tp = {
110128
.max_x = 2794,
111129
.max_y = 1758,
@@ -259,6 +277,9 @@ static int asus_raw_event(struct hid_device *hdev,
259277
{
260278
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
261279

280+
if (drvdata->battery && data[0] == BATTERY_REPORT_ID)
281+
return asus_report_battery(drvdata, data, size);
282+
262283
if (drvdata->tp && data[0] == INPUT_REPORT_ID)
263284
return asus_report_input(drvdata, data, size);
264285

@@ -428,6 +449,164 @@ static int asus_kbd_register_leds(struct hid_device *hdev)
428449
return ret;
429450
}
430451

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+
431610
static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
432611
{
433612
struct input_dev *input = hi->input;
@@ -500,7 +679,7 @@ static int asus_input_mapping(struct hid_device *hdev,
500679
* This avoids a bunch of non-functional hid_input devices getting
501680
* created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
502681
*/
503-
if (drvdata->quirks & QUIRK_T100CHI) {
682+
if (drvdata->quirks & (QUIRK_T100CHI | QUIRK_T90CHI)) {
504683
if (field->application == (HID_UP_GENDESK | 0x0080) ||
505684
usage->hid == (HID_UP_GENDEVCTRLS | 0x0024) ||
506685
usage->hid == (HID_UP_GENDEVCTRLS | 0x0025) ||
@@ -660,6 +839,15 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
660839

661840
drvdata->quirks = id->driver_data;
662841

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+
663851
if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
664852
drvdata->tp = &asus_i2c_tp;
665853

@@ -694,6 +882,17 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
694882
if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
695883
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
696884

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+
697896
ret = hid_parse(hdev);
698897
if (ret) {
699898
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,
769968
hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
770969
rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
771970
}
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+
775984
/*
776985
* Change Usage (76h) to Usage Minimum (00h), Usage Maximum
777986
* (FFh) and clear the flags in the Input() byte.
778987
* Note the descriptor has a bogus 0 byte at the end so we
779988
* only need 1 extra byte.
780989
*/
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+
}
7931007
}
1008+
7941009
if (drvdata->quirks & QUIRK_G752_KEYBOARD &&
7951010
*rsize == 75 && rdesc[61] == 0x15 && rdesc[62] == 0x00) {
7961011
/* report is missing usage mninum and maximum */

drivers/hid/hid-elan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ static int elan_start_multitouch(struct hid_device *hdev)
393393
* This byte sequence will enable multitouch mode and disable
394394
* mouse emulation
395395
*/
396-
const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
396+
static const unsigned char buf[] = { 0x0D, 0x00, 0x03, 0x21, 0x00 };
397397
unsigned char *dmabuf = kmemdup(buf, sizeof(buf), GFP_KERNEL);
398398

399399
if (!dmabuf)

0 commit comments

Comments
 (0)