* [PATCH 1/5] HID: asus: Parameterize the touchpad code
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
@ 2017-07-02 14:34 ` Hans de Goede
2017-07-02 14:34 ` [PATCH 2/5] HID: asus: Fix T100TA touchpad y dimensions Hans de Goede
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2017-07-02 14:34 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Hans de Goede, linux-input
Instead of having hardcoded (#define-d) values use a struct describing
the various touchpad parameters. This is a preparation patch for
improving the T100TA touchpad support as well as for adding T100CHI
touchpad support.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/hid/hid-asus.c | 114 +++++++++++++++++++++++++++++--------------------
1 file changed, 67 insertions(+), 47 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index b5887eaedfca..4632481c5ab7 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -44,22 +44,13 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
#define FEATURE_KBD_REPORT_ID 0x5a
-
-#define INPUT_REPORT_SIZE 28
#define FEATURE_KBD_REPORT_SIZE 16
#define SUPPORT_KBD_BACKLIGHT BIT(0)
-#define MAX_CONTACTS 5
-
-#define MAX_X 2794
-#define MAX_X_T100 2240
-#define MAX_Y 1758
#define MAX_TOUCH_MAJOR 8
#define MAX_PRESSURE 128
-#define CONTACT_DATA_SIZE 5
-
#define BTN_LEFT_MASK 0x01
#define CONTACT_TOOL_TYPE_MASK 0x80
#define CONTACT_X_MSB_MASK 0xf0
@@ -74,12 +65,11 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_NO_CONSUMER_USAGES BIT(4)
#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
#define QUIRK_T100_KEYBOARD BIT(6)
-#define QUIRK_T100_TOUCHPAD BIT(7)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
QUIRK_NO_CONSUMER_USAGES)
-#define TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \
+#define I2C_TOUCHPAD_QUIRKS (QUIRK_NO_INIT_REPORTS | \
QUIRK_SKIP_INPUT_MAPPING | \
QUIRK_IS_MULTITOUCH)
@@ -93,19 +83,43 @@ struct asus_kbd_leds {
bool removed;
};
+struct asus_touchpad_info {
+ int max_x;
+ int max_y;
+ int contact_size;
+ int max_contacts;
+};
+
struct asus_drvdata {
unsigned long quirks;
struct input_dev *input;
struct asus_kbd_leds *kbd_backlight;
+ const struct asus_touchpad_info *tp;
bool enable_backlight;
};
-static void asus_report_contact_down(struct input_dev *input,
+static const struct asus_touchpad_info asus_i2c_tp = {
+ .max_x = 2794,
+ .max_y = 1758,
+ .contact_size = 5,
+ .max_contacts = 5,
+};
+
+static const struct asus_touchpad_info asus_t100ta_tp = {
+ .max_x = 2240,
+ .max_y = 1758,
+ .contact_size = 5,
+ .max_contacts = 5,
+};
+
+static void asus_report_contact_down(struct asus_drvdata *drvdat,
int toolType, u8 *data)
{
- int touch_major, pressure;
- int x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
- int y = MAX_Y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
+ struct input_dev *input = drvdat->input;
+ int touch_major, pressure, x, y;
+
+ x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
+ y = drvdat->tp->max_y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
if (toolType == MT_TOOL_PALM) {
touch_major = MAX_TOUCH_MAJOR;
@@ -122,9 +136,9 @@ static void asus_report_contact_down(struct input_dev *input,
}
/* Required for Synaptics Palm Detection */
-static void asus_report_tool_width(struct input_dev *input)
+static void asus_report_tool_width(struct asus_drvdata *drvdat)
{
- struct input_mt *mt = input->mt;
+ struct input_mt *mt = drvdat->input->mt;
struct input_mt_slot *oldest;
int oldid, count, i;
@@ -146,35 +160,40 @@ static void asus_report_tool_width(struct input_dev *input)
}
if (oldest) {
- input_report_abs(input, ABS_TOOL_WIDTH,
+ input_report_abs(drvdat->input, ABS_TOOL_WIDTH,
input_mt_get_value(oldest, ABS_MT_TOUCH_MAJOR));
}
}
-static void asus_report_input(struct input_dev *input, u8 *data)
+static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size)
{
int i;
u8 *contactData = data + 2;
- for (i = 0; i < MAX_CONTACTS; i++) {
+ if (size != 3 + drvdat->tp->contact_size * drvdat->tp->max_contacts)
+ return 0;
+
+ for (i = 0; i < drvdat->tp->max_contacts; i++) {
bool down = !!(data[1] & BIT(i+3));
int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
MT_TOOL_PALM : MT_TOOL_FINGER;
- input_mt_slot(input, i);
- input_mt_report_slot_state(input, toolType, down);
+ input_mt_slot(drvdat->input, i);
+ input_mt_report_slot_state(drvdat->input, toolType, down);
if (down) {
- asus_report_contact_down(input, toolType, contactData);
- contactData += CONTACT_DATA_SIZE;
+ asus_report_contact_down(drvdat, toolType, contactData);
+ contactData += drvdat->tp->contact_size;
}
}
- input_report_key(input, BTN_LEFT, data[1] & BTN_LEFT_MASK);
- asus_report_tool_width(input);
+ input_report_key(drvdat->input, BTN_LEFT, data[1] & BTN_LEFT_MASK);
+ asus_report_tool_width(drvdat);
+
+ input_mt_sync_frame(drvdat->input);
+ input_sync(drvdat->input);
- input_mt_sync_frame(input);
- input_sync(input);
+ return 1;
}
static int asus_raw_event(struct hid_device *hdev,
@@ -182,12 +201,8 @@ static int asus_raw_event(struct hid_device *hdev,
{
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
- if (drvdata->quirks & QUIRK_IS_MULTITOUCH &&
- data[0] == INPUT_REPORT_ID &&
- size == INPUT_REPORT_SIZE) {
- asus_report_input(drvdata->input, data);
- return 1;
- }
+ if (drvdata->tp && data[0] == INPUT_REPORT_ID)
+ return asus_report_input(drvdata, data, size);
return 0;
}
@@ -339,14 +354,13 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
struct input_dev *input = hi->input;
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
- if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+ if (drvdata->tp) {
int ret;
- if (drvdata->quirks & QUIRK_T100_TOUCHPAD)
- input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X_T100, 0, 0);
- else
- input_set_abs_params(input, ABS_MT_POSITION_X, 0, MAX_X, 0, 0);
- input_set_abs_params(input, ABS_MT_POSITION_Y, 0, MAX_Y, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_X, 0,
+ drvdata->tp->max_x, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
+ drvdata->tp->max_y, 0, 0);
input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
@@ -354,7 +368,8 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
__set_bit(BTN_LEFT, input->keybit);
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
- ret = input_mt_init_slots(input, MAX_CONTACTS, INPUT_MT_POINTER);
+ ret = input_mt_init_slots(input, drvdata->tp->max_contacts,
+ INPUT_MT_POINTER);
if (ret) {
hid_err(hdev, "Asus input mt init slots failed: %d\n", ret);
@@ -477,7 +492,7 @@ static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
{
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
- if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
+ if (drvdata->tp)
return asus_start_multitouch(hdev);
return 0;
@@ -498,11 +513,16 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
drvdata->quirks = id->driver_data;
+ if (drvdata->quirks & QUIRK_IS_MULTITOUCH)
+ drvdata->tp = &asus_i2c_tp;
+
if (drvdata->quirks & QUIRK_T100_KEYBOARD) {
struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
- if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF)
- drvdata->quirks = TOUCHPAD_QUIRKS | QUIRK_T100_TOUCHPAD;
+ if (intf->altsetting->desc.bInterfaceNumber == T100_TPAD_INTF) {
+ drvdata->quirks = QUIRK_SKIP_INPUT_MAPPING;
+ drvdata->tp = &asus_t100ta_tp;
+ }
}
if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
@@ -526,13 +546,13 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_stop_hw;
}
- if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+ if (drvdata->tp) {
drvdata->input->name = "Asus TouchPad";
} else {
drvdata->input->name = "Asus Keyboard";
}
- if (drvdata->quirks & QUIRK_IS_MULTITOUCH) {
+ if (drvdata->tp) {
ret = asus_start_multitouch(hdev);
if (ret)
goto err_stop_hw;
@@ -579,7 +599,7 @@ static const struct hid_device_id asus_devices[] = {
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD), I2C_KEYBOARD_QUIRKS},
{ HID_I2C_DEVICE(USB_VENDOR_ID_ASUSTEK,
- USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), TOUCHPAD_QUIRKS },
+ USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD), I2C_TOUCHPAD_QUIRKS },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] HID: asus: Fix T100TA touchpad y dimensions
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
2017-07-02 14:34 ` [PATCH 1/5] HID: asus: Parameterize the touchpad code Hans de Goede
@ 2017-07-02 14:34 ` Hans de Goede
2017-07-02 14:34 ` [PATCH 3/5] HID: asus: Add T100TA touchpad resolution info Hans de Goede
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2017-07-02 14:34 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Hans de Goede, linux-input
When adding the initial support I only looked at the maximum coordinates
but the Y axis is inverted, so I should have checked the minimum
coodinates which never reach 0 due to max_y being wrong, fix this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/hid/hid-asus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 4632481c5ab7..4ff4add14974 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -107,7 +107,7 @@ static const struct asus_touchpad_info asus_i2c_tp = {
static const struct asus_touchpad_info asus_t100ta_tp = {
.max_x = 2240,
- .max_y = 1758,
+ .max_y = 1120,
.contact_size = 5,
.max_contacts = 5,
};
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] HID: asus: Add T100TA touchpad resolution info
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
2017-07-02 14:34 ` [PATCH 1/5] HID: asus: Parameterize the touchpad code Hans de Goede
2017-07-02 14:34 ` [PATCH 2/5] HID: asus: Fix T100TA touchpad y dimensions Hans de Goede
@ 2017-07-02 14:34 ` Hans de Goede
2017-07-02 14:34 ` [PATCH 4/5] HID: asus: Add T100CHI bluetooth keyboard dock special keys mapping Hans de Goede
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2017-07-02 14:34 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Hans de Goede, linux-input
The touchpad code is only used with the T100TA touchpad which
measures 75.5 x 41.5 mm, add corresponding resolution info.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/hid/hid-asus.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index 4ff4add14974..e27cc4a25ed0 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -86,6 +86,8 @@ struct asus_kbd_leds {
struct asus_touchpad_info {
int max_x;
int max_y;
+ int res_x;
+ int res_y;
int contact_size;
int max_contacts;
};
@@ -108,6 +110,8 @@ static const struct asus_touchpad_info asus_i2c_tp = {
static const struct asus_touchpad_info asus_t100ta_tp = {
.max_x = 2240,
.max_y = 1120,
+ .res_x = 30, /* units/mm */
+ .res_y = 27, /* units/mm */
.contact_size = 5,
.max_contacts = 5,
};
@@ -361,6 +365,8 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
drvdata->tp->max_x, 0, 0);
input_set_abs_params(input, ABS_MT_POSITION_Y, 0,
drvdata->tp->max_y, 0, 0);
+ input_abs_set_res(input, ABS_MT_POSITION_X, drvdata->tp->res_x);
+ input_abs_set_res(input, ABS_MT_POSITION_Y, drvdata->tp->res_y);
input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] HID: asus: Add T100CHI bluetooth keyboard dock special keys mapping
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
` (2 preceding siblings ...)
2017-07-02 14:34 ` [PATCH 3/5] HID: asus: Add T100TA touchpad resolution info Hans de Goede
@ 2017-07-02 14:34 ` Hans de Goede
2017-07-02 14:34 ` [PATCH 5/5] HID: asus: Add T100CHI bluetooth keyboard dock touchpad support Hans de Goede
2017-07-20 14:04 ` [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Jiri Kosina
5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2017-07-02 14:34 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Hans de Goede, linux-input
The Asus Transformer T100CHI comes with a Bluetooth keyboard dock which
uses the same 0xff31 Asus vendor HUT page as other Asus keyboards.
This commit adds its device-id to hid-asus and fixes an issue in the
descriptor of the 0xff31 Usage, which together fixes the special keys
on this keyboard not working.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/hid/hid-asus.c | 26 ++++++++++++++++++++++++++
drivers/hid/hid-core.c | 1 +
drivers/hid/hid-ids.h | 1 +
3 files changed, 28 insertions(+)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index e27cc4a25ed0..d5519479142f 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -65,6 +65,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define QUIRK_NO_CONSUMER_USAGES BIT(4)
#define QUIRK_USE_KBD_BACKLIGHT BIT(5)
#define QUIRK_T100_KEYBOARD BIT(6)
+#define QUIRK_T100CHI BIT(7)
#define I2C_KEYBOARD_QUIRKS (QUIRK_FIX_NOTEBOOK_REPORT | \
QUIRK_NO_INIT_REPORTS | \
@@ -592,11 +593,34 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
hid_info(hdev, "Fixing up Asus notebook report descriptor\n");
rdesc[55] = 0xdd;
}
+ /* For the T100TA keyboard dock */
if (drvdata->quirks & QUIRK_T100_KEYBOARD &&
*rsize == 76 && rdesc[73] == 0x81 && rdesc[74] == 0x01) {
hid_info(hdev, "Fixing up Asus T100 keyb report descriptor\n");
rdesc[74] &= ~HID_MAIN_ITEM_CONSTANT;
}
+ /* For the T100CHI keyboard dock */
+ if (drvdata->quirks & QUIRK_T100CHI &&
+ *rsize == 403 && rdesc[388] == 0x09 && rdesc[389] == 0x76) {
+ /*
+ * Change Usage (76h) to Usage Minimum (00h), Usage Maximum
+ * (FFh) and clear the flags in the Input() byte.
+ * Note the descriptor has a bogus 0 byte at the end so we
+ * only need 1 extra byte.
+ */
+ *rsize = 404;
+ rdesc = kmemdup(rdesc, *rsize, GFP_KERNEL);
+ if (!rdesc)
+ return NULL;
+
+ hid_info(hdev, "Fixing up T100CHI keyb report descriptor\n");
+ memmove(rdesc + 392, rdesc + 390, 12);
+ rdesc[388] = 0x19;
+ rdesc[389] = 0x00;
+ rdesc[390] = 0x29;
+ rdesc[391] = 0xff;
+ rdesc[402] = 0x00;
+ }
return rdesc;
}
@@ -613,6 +637,8 @@ static const struct hid_device_id asus_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK,
USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD),
QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK,
+ USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), QUIRK_T100CHI },
{ }
};
MODULE_DEVICE_TABLE(hid, asus_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index bf7f46e8a022..6220e6e8e979 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1892,6 +1892,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD) },
#endif
#if IS_ENABLED(CONFIG_HID_AUREAL)
{ HID_USB_DEVICE(USB_VENDOR_ID_AUREAL, USB_DEVICE_ID_AUREAL_W01RN) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 8acd1b779f6d..73b440c822e9 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -174,6 +174,7 @@
#define USB_DEVICE_ID_ASUSTEK_LCM 0x1726
#define USB_DEVICE_ID_ASUSTEK_LCM2 0x175b
#define USB_DEVICE_ID_ASUSTEK_T100_KEYBOARD 0x17e0
+#define USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD 0x8502
#define USB_DEVICE_ID_ASUSTEK_I2C_KEYBOARD 0x8585
#define USB_DEVICE_ID_ASUSTEK_I2C_TOUCHPAD 0x0101
#define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD1 0x1854
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] HID: asus: Add T100CHI bluetooth keyboard dock touchpad support
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
` (3 preceding siblings ...)
2017-07-02 14:34 ` [PATCH 4/5] HID: asus: Add T100CHI bluetooth keyboard dock special keys mapping Hans de Goede
@ 2017-07-02 14:34 ` Hans de Goede
2017-07-20 14:04 ` [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Jiri Kosina
5 siblings, 0 replies; 7+ messages in thread
From: Hans de Goede @ 2017-07-02 14:34 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires; +Cc: Hans de Goede, linux-input
Put the touchpad in native (absolute coordinate mode) and export it to
userspace as a touchpad rather then as a mouse.
Note this requires HID_QUIRK_MULTI_INPUT as the T100CHI keyboard dock
has all functionality on a single HID interface and userspace expects
touchpads to be on a separate input_dev. Without MULTI_INPUT userspace
will ignore the keyboard part of the keyboard/touchpad combo.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/hid/hid-asus.c | 74 +++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 67 insertions(+), 7 deletions(-)
diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
index d5519479142f..b9804c7b9028 100644
--- a/drivers/hid/hid-asus.c
+++ b/drivers/hid/hid-asus.c
@@ -41,6 +41,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
#define T100_TPAD_INTF 2
+#define T100CHI_MOUSE_REPORT_ID 0x06
#define FEATURE_REPORT_ID 0x0d
#define INPUT_REPORT_ID 0x5d
#define FEATURE_KBD_REPORT_ID 0x5a
@@ -117,6 +118,15 @@ static const struct asus_touchpad_info asus_t100ta_tp = {
.max_contacts = 5,
};
+static const struct asus_touchpad_info asus_t100chi_tp = {
+ .max_x = 2640,
+ .max_y = 1320,
+ .res_x = 31, /* units/mm */
+ .res_y = 29, /* units/mm */
+ .contact_size = 3,
+ .max_contacts = 4,
+};
+
static void asus_report_contact_down(struct asus_drvdata *drvdat,
int toolType, u8 *data)
{
@@ -126,6 +136,12 @@ static void asus_report_contact_down(struct asus_drvdata *drvdat,
x = (data[0] & CONTACT_X_MSB_MASK) << 4 | data[1];
y = drvdat->tp->max_y - ((data[0] & CONTACT_Y_MSB_MASK) << 8 | data[2]);
+ input_report_abs(input, ABS_MT_POSITION_X, x);
+ input_report_abs(input, ABS_MT_POSITION_Y, y);
+
+ if (drvdat->tp->contact_size < 5)
+ return;
+
if (toolType == MT_TOOL_PALM) {
touch_major = MAX_TOUCH_MAJOR;
pressure = MAX_PRESSURE;
@@ -134,8 +150,6 @@ static void asus_report_contact_down(struct asus_drvdata *drvdat,
pressure = data[4] & CONTACT_PRESSURE_MASK;
}
- input_report_abs(input, ABS_MT_POSITION_X, x);
- input_report_abs(input, ABS_MT_POSITION_Y, y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major);
input_report_abs(input, ABS_MT_PRESSURE, pressure);
}
@@ -147,6 +161,9 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat)
struct input_mt_slot *oldest;
int oldid, count, i;
+ if (drvdat->tp->contact_size < 5)
+ return;
+
oldest = NULL;
oldid = mt->trkid;
count = 0;
@@ -172,7 +189,7 @@ static void asus_report_tool_width(struct asus_drvdata *drvdat)
static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size)
{
- int i;
+ int i, toolType = MT_TOOL_FINGER;
u8 *contactData = data + 2;
if (size != 3 + drvdat->tp->contact_size * drvdat->tp->max_contacts)
@@ -180,7 +197,9 @@ static int asus_report_input(struct asus_drvdata *drvdat, u8 *data, int size)
for (i = 0; i < drvdat->tp->max_contacts; i++) {
bool down = !!(data[1] & BIT(i+3));
- int toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
+
+ if (drvdat->tp->contact_size >= 5)
+ toolType = contactData[3] & CONTACT_TOOL_TYPE_MASK ?
MT_TOOL_PALM : MT_TOOL_FINGER;
input_mt_slot(drvdat->input, i);
@@ -359,6 +378,11 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
struct input_dev *input = hi->input;
struct asus_drvdata *drvdata = hid_get_drvdata(hdev);
+ /* T100CHI uses MULTI_INPUT, bind the touchpad to the mouse hid_input */
+ if (drvdata->quirks & QUIRK_T100CHI &&
+ hi->report->id != T100CHI_MOUSE_REPORT_ID)
+ return 0;
+
if (drvdata->tp) {
int ret;
@@ -368,9 +392,15 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
drvdata->tp->max_y, 0, 0);
input_abs_set_res(input, ABS_MT_POSITION_X, drvdata->tp->res_x);
input_abs_set_res(input, ABS_MT_POSITION_Y, drvdata->tp->res_y);
- input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MAX_TOUCH_MAJOR, 0, 0);
- input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0);
- input_set_abs_params(input, ABS_MT_PRESSURE, 0, MAX_PRESSURE, 0, 0);
+
+ if (drvdata->tp->contact_size >= 5) {
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0,
+ MAX_TOUCH_MAJOR, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0,
+ MAX_TOUCH_MAJOR, 0, 0);
+ input_set_abs_params(input, ABS_MT_PRESSURE, 0,
+ MAX_PRESSURE, 0, 0);
+ }
__set_bit(BTN_LEFT, input->keybit);
__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
@@ -408,6 +438,26 @@ static int asus_input_mapping(struct hid_device *hdev,
return -1;
}
+ /*
+ * Ignore a bunch of bogus collections in the T100CHI descriptor.
+ * This avoids a bunch of non-functional hid_input devices getting
+ * created because of the T100CHI using HID_QUIRK_MULTI_INPUT.
+ */
+ if (drvdata->quirks & QUIRK_T100CHI) {
+ if (field->application == (HID_UP_GENDESK | 0x0080) ||
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0024) ||
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0025) ||
+ usage->hid == (HID_UP_GENDEVCTRLS | 0x0026))
+ return -1;
+ /*
+ * We use the hid_input for the mouse report for the touchpad,
+ * keep the left button, to avoid the core removing it.
+ */
+ if (field->application == HID_GD_MOUSE &&
+ usage->hid != (HID_UP_BUTTON | 1))
+ return -1;
+ }
+
/* ASUS-specific keyboard hotkeys */
if ((usage->hid & HID_USAGE_PAGE) == 0xff310000) {
set_bit(EV_REP, hi->input->evbit);
@@ -532,6 +582,16 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
}
+ if (drvdata->quirks & QUIRK_T100CHI) {
+ /*
+ * All functionality is on a single HID interface and for
+ * userspace the touchpad must be a separate input_dev.
+ */
+ hdev->quirks |= HID_QUIRK_MULTI_INPUT |
+ HID_QUIRK_NO_EMPTY_INPUT;
+ drvdata->tp = &asus_t100chi_tp;
+ }
+
if (drvdata->quirks & QUIRK_NO_INIT_REPORTS)
hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS;
--
2.13.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/5] HID: asus: T100 keyboard dock support improvements
2017-07-02 14:34 [PATCH 1/5] HID: asus: T100 keyboard dock support improvements Hans de Goede
` (4 preceding siblings ...)
2017-07-02 14:34 ` [PATCH 5/5] HID: asus: Add T100CHI bluetooth keyboard dock touchpad support Hans de Goede
@ 2017-07-20 14:04 ` Jiri Kosina
5 siblings, 0 replies; 7+ messages in thread
From: Jiri Kosina @ 2017-07-20 14:04 UTC (permalink / raw)
To: Hans de Goede; +Cc: Benjamin Tissoires, linux-input
On Sun, 2 Jul 2017, Hans de Goede wrote:
> Here is a patch series with some further improvements for
> the keyboard docks of Asus Transformer T100* 2-in-1s.
I've applied all but the last patch to for-4.14/asus.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply [flat|nested] 7+ messages in thread