Add Surface 3 touch cover fixes
Should make the touchpad multitouch work without breaking the CapsLock LED.
This commit is contained in:
parent
999484ba1d
commit
d884e8fd12
|
@ -0,0 +1,187 @@
|
|||
From de1715d88a5e80cc14455db1cf758cdf970fff22 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
Date: Thu, 12 May 2016 15:47:27 +0200
|
||||
Subject: [PATCH 1/3] HID: input: rework HID_QUIRK_MULTI_INPUT
|
||||
|
||||
The purpose of HID_QUIRK_MULTI_INPUT is to have an input device per
|
||||
report id. This is useful when the HID device presents several HID
|
||||
collections of different device types.
|
||||
|
||||
The current implementation of hid-input creates one input node per id per
|
||||
type (input or output). This is problematic for the LEDs of a keyboard as
|
||||
they are often set through an output report. The current code creates
|
||||
one input node with all the keyboard keys, and one other with only the
|
||||
LEDs.
|
||||
|
||||
To solve this, we use a two-passes way:
|
||||
- first, we initialize all input nodes and associate one per report id
|
||||
- then, we register all the input nodes
|
||||
|
||||
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
---
|
||||
drivers/hid/hid-input.c | 95 ++++++++++++++++++++++++++++---------------------
|
||||
include/linux/hid.h | 1 +
|
||||
2 files changed, 55 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
|
||||
index bcfaf32..bb2ec45 100644
|
||||
--- a/drivers/hid/hid-input.c
|
||||
+++ b/drivers/hid/hid-input.c
|
||||
@@ -1458,6 +1458,31 @@ static void hidinput_cleanup_hidinput(struct hid_device *hid,
|
||||
kfree(hidinput);
|
||||
}
|
||||
|
||||
+static struct hid_input *hidinput_match(struct hid_report *report)
|
||||
+{
|
||||
+ struct hid_device *hid = report->device;
|
||||
+ struct hid_input *hidinput;
|
||||
+
|
||||
+ list_for_each_entry(hidinput, &hid->inputs, list) {
|
||||
+ if (hidinput->report &&
|
||||
+ hidinput->report->id == report->id)
|
||||
+ return hidinput;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static inline void hidinput_configure_usages(struct hid_input *hidinput,
|
||||
+ struct hid_report *report)
|
||||
+{
|
||||
+ int i, j;
|
||||
+
|
||||
+ for (i = 0; i < report->maxfield; i++)
|
||||
+ for (j = 0; j < report->field[i]->maxusage; j++)
|
||||
+ hidinput_configure_usage(hidinput, report->field[i],
|
||||
+ report->field[i]->usage + j);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Register the input device; print a message.
|
||||
* Configure the input layer interface
|
||||
@@ -1468,8 +1493,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
||||
{
|
||||
struct hid_driver *drv = hid->driver;
|
||||
struct hid_report *report;
|
||||
- struct hid_input *hidinput = NULL;
|
||||
- int i, j, k;
|
||||
+ struct hid_input *next, *hidinput = NULL;
|
||||
+ int i, k;
|
||||
|
||||
INIT_LIST_HEAD(&hid->inputs);
|
||||
INIT_WORK(&hid->led_work, hidinput_led_worker);
|
||||
@@ -1499,43 +1524,40 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
||||
if (!report->maxfield)
|
||||
continue;
|
||||
|
||||
+ /*
|
||||
+ * Find the previous hidinput report attached
|
||||
+ * to this report id.
|
||||
+ */
|
||||
+ if (hid->quirks & HID_QUIRK_MULTI_INPUT)
|
||||
+ hidinput = hidinput_match(report);
|
||||
+
|
||||
if (!hidinput) {
|
||||
hidinput = hidinput_allocate(hid);
|
||||
if (!hidinput)
|
||||
goto out_unwind;
|
||||
}
|
||||
|
||||
- for (i = 0; i < report->maxfield; i++)
|
||||
- for (j = 0; j < report->field[i]->maxusage; j++)
|
||||
- hidinput_configure_usage(hidinput, report->field[i],
|
||||
- report->field[i]->usage + j);
|
||||
-
|
||||
- if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
||||
- !hidinput_has_been_populated(hidinput))
|
||||
- continue;
|
||||
+ hidinput_configure_usages(hidinput, report);
|
||||
|
||||
- if (hid->quirks & HID_QUIRK_MULTI_INPUT) {
|
||||
- /* This will leave hidinput NULL, so that it
|
||||
- * allocates another one if we have more inputs on
|
||||
- * the same interface. Some devices (e.g. Happ's
|
||||
- * UGCI) cram a lot of unrelated inputs into the
|
||||
- * same interface. */
|
||||
+ if (hid->quirks & HID_QUIRK_MULTI_INPUT)
|
||||
hidinput->report = report;
|
||||
- if (drv->input_configured &&
|
||||
- drv->input_configured(hid, hidinput))
|
||||
- goto out_cleanup;
|
||||
- if (input_register_device(hidinput->input))
|
||||
- goto out_cleanup;
|
||||
- hidinput = NULL;
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
- if (hidinput && (hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
||||
- !hidinput_has_been_populated(hidinput)) {
|
||||
- /* no need to register an input device not populated */
|
||||
- hidinput_cleanup_hidinput(hid, hidinput);
|
||||
- hidinput = NULL;
|
||||
+ list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
|
||||
+ if ((hid->quirks & HID_QUIRK_NO_EMPTY_INPUT) &&
|
||||
+ !hidinput_has_been_populated(hidinput)) {
|
||||
+ /* no need to register an input device not populated */
|
||||
+ hidinput_cleanup_hidinput(hid, hidinput);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (drv->input_configured &&
|
||||
+ drv->input_configured(hid, hidinput))
|
||||
+ goto out_unwind;
|
||||
+ if (input_register_device(hidinput->input))
|
||||
+ goto out_unwind;
|
||||
+ hidinput->registered = true;
|
||||
}
|
||||
|
||||
if (list_empty(&hid->inputs)) {
|
||||
@@ -1543,20 +1565,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
|
||||
goto out_unwind;
|
||||
}
|
||||
|
||||
- if (hidinput) {
|
||||
- if (drv->input_configured &&
|
||||
- drv->input_configured(hid, hidinput))
|
||||
- goto out_cleanup;
|
||||
- if (input_register_device(hidinput->input))
|
||||
- goto out_cleanup;
|
||||
- }
|
||||
-
|
||||
return 0;
|
||||
|
||||
-out_cleanup:
|
||||
- list_del(&hidinput->list);
|
||||
- input_free_device(hidinput->input);
|
||||
- kfree(hidinput);
|
||||
out_unwind:
|
||||
/* unwind the ones we already registered */
|
||||
hidinput_disconnect(hid);
|
||||
@@ -1573,7 +1583,10 @@ void hidinput_disconnect(struct hid_device *hid)
|
||||
|
||||
list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
|
||||
list_del(&hidinput->list);
|
||||
- input_unregister_device(hidinput->input);
|
||||
+ if (hidinput->registered)
|
||||
+ input_unregister_device(hidinput->input);
|
||||
+ else
|
||||
+ input_free_device(hidinput->input);
|
||||
kfree(hidinput);
|
||||
}
|
||||
|
||||
diff --git a/include/linux/hid.h b/include/linux/hid.h
|
||||
index 75b66ec..8a5d697 100644
|
||||
--- a/include/linux/hid.h
|
||||
+++ b/include/linux/hid.h
|
||||
@@ -479,6 +479,7 @@ struct hid_input {
|
||||
struct list_head list;
|
||||
struct hid_report *report;
|
||||
struct input_dev *input;
|
||||
+ bool registered;
|
||||
};
|
||||
|
||||
enum hid_type {
|
||||
--
|
||||
2.7.4
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
From 0e81c6dd0106dfb2ddb065077f596756ea429adc Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
Date: Thu, 12 May 2016 15:32:08 +0200
|
||||
Subject: [PATCH 2/3] HID: multitouch: enable the Surface 3 Type Cover to
|
||||
report multitouch data
|
||||
|
||||
There is no reasons to filter out keyboard and consumer control collections
|
||||
in hid-multitouch.
|
||||
With the previous hid-input fix, there is now a full support of the Type
|
||||
Cover and we can remove all specific bits from hid-core and hid-microsoft.
|
||||
|
||||
hid-multitouch will automatically set HID_QUIRK_NO_INIT_REPORTS so we can
|
||||
also remove it from the list of ushbid quirks.
|
||||
|
||||
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
---
|
||||
drivers/hid/hid-core.c | 2 --
|
||||
drivers/hid/hid-ids.h | 1 -
|
||||
drivers/hid/hid-microsoft.c | 2 --
|
||||
drivers/hid/hid-multitouch.c | 4 +++-
|
||||
drivers/hid/usbhid/hid-quirks.c | 1 -
|
||||
5 files changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||||
index efd8f8c..1bbbe6c 100644
|
||||
--- a/drivers/hid/hid-core.c
|
||||
+++ b/drivers/hid/hid-core.c
|
||||
@@ -727,7 +727,6 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type)
|
||||
(hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 ||
|
||||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 ||
|
||||
hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP ||
|
||||
- hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 ||
|
||||
hid->product == USB_DEVICE_ID_MS_POWER_COVER) &&
|
||||
hid->group == HID_GROUP_MULTITOUCH)
|
||||
hid->group = HID_GROUP_GENERIC;
|
||||
@@ -1979,7 +1978,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) },
|
||||
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3KV1) },
|
||||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||
index 191c981..c54d0a9 100644
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -708,7 +708,6 @@
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2
|
||||
#define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd
|
||||
-#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de
|
||||
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
||||
|
||||
#define USB_VENDOR_ID_MOJO 0x8282
|
||||
diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c
|
||||
index e924d55..cf6920b 100644
|
||||
--- a/drivers/hid/hid-microsoft.c
|
||||
+++ b/drivers/hid/hid-microsoft.c
|
||||
@@ -288,8 +288,6 @@ static const struct hid_device_id ms_devices[] = {
|
||||
.driver_data = MS_HIDINPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP),
|
||||
.driver_data = MS_HIDINPUT },
|
||||
- { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3),
|
||||
- .driver_data = MS_HIDINPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER),
|
||||
.driver_data = MS_HIDINPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_KEYBOARD),
|
||||
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||
index 95b7d61..dd279d7 100644
|
||||
--- a/drivers/hid/hid-multitouch.c
|
||||
+++ b/drivers/hid/hid-multitouch.c
|
||||
@@ -835,7 +835,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
if (!td->mtclass.export_all_inputs &&
|
||||
field->application != HID_DG_TOUCHSCREEN &&
|
||||
field->application != HID_DG_PEN &&
|
||||
- field->application != HID_DG_TOUCHPAD)
|
||||
+ field->application != HID_DG_TOUCHPAD &&
|
||||
+ field->application != HID_GD_KEYBOARD &&
|
||||
+ field->application != HID_CP_CONSUMER_CONTROL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
|
||||
index b4b8c6a..baf2bad 100644
|
||||
--- a/drivers/hid/usbhid/hid-quirks.c
|
||||
+++ b/drivers/hid/usbhid/hid-quirks.c
|
||||
@@ -98,7 +98,6 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS },
|
||||
- { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS },
|
||||
--
|
||||
2.7.4
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
From d4b0c0bfd2194496d7a72722829d4283ed5f3141 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
Date: Fri, 3 Jun 2016 11:49:17 +0200
|
||||
Subject: [PATCH 3/3] HID: multitouch: set correct class for Surface Type Cover
|
||||
3
|
||||
|
||||
Looks like Microsoft forgot to set the blob discriminating between Win 8
|
||||
and Win 7 devices...
|
||||
|
||||
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
|
||||
---
|
||||
drivers/hid/hid-multitouch.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
|
||||
index dd279d7..fa6622a 100644
|
||||
--- a/drivers/hid/hid-multitouch.c
|
||||
+++ b/drivers/hid/hid-multitouch.c
|
||||
@@ -1379,6 +1379,10 @@ static const struct hid_device_id mt_devices[] = {
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ILITEK,
|
||||
USB_DEVICE_ID_ILITEK_MULTITOUCH) },
|
||||
|
||||
+ /* Microsoft */
|
||||
+ { .driver_data = MT_CLS_WIN_8,
|
||||
+ MT_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x07cd) },
|
||||
+
|
||||
/* MosArt panels */
|
||||
{ .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_ASUS,
|
||||
--
|
||||
2.7.4
|
||||
|
|
@ -635,6 +635,10 @@ Patch900: 0001-Input-add-new-driver-for-the-Surface-3.patch
|
|||
Patch901: 0001-Input-surface3_spi-Prepare-to-add-support-for-Surfac.patch
|
||||
Patch902: 0001-Input-surface3_spi-add-surface-pen-support-for-Surfa.patch
|
||||
|
||||
Patch903: 0001-HID-input-rework-HID_QUIRK_MULTI_INPUT.patch
|
||||
Patch904: 0002-HID-multitouch-enable-the-Surface-3-Type-Cover-to-re.patch
|
||||
Patch905: 0003-HID-multitouch-set-correct-class-for-Surface-Type-Co.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
%endif
|
||||
|
|
Loading…
Reference in New Issue