mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'for-7.2/multitouch' into for-linus
- UX improvement fixes for Yoga Book 9 (Dave Carey)
This commit is contained in:
commit
df1d6781b2
|
|
@ -443,11 +443,14 @@ static const struct mt_class mt_classes[] = {
|
|||
MT_QUIRK_CONTACT_CNT_ACCURATE,
|
||||
},
|
||||
{ .name = MT_CLS_YOGABOOK9I,
|
||||
.quirks = MT_QUIRK_ALWAYS_VALID |
|
||||
.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
|
||||
MT_QUIRK_ALWAYS_VALID |
|
||||
MT_QUIRK_CONTACT_CNT_ACCURATE |
|
||||
MT_QUIRK_FORCE_MULTI_INPUT |
|
||||
MT_QUIRK_SEPARATE_APP_REPORT |
|
||||
MT_QUIRK_HOVERING |
|
||||
MT_QUIRK_YOGABOOK9I,
|
||||
.maxcontacts = 10,
|
||||
.export_all_inputs = true
|
||||
},
|
||||
{ .name = MT_CLS_EGALAX_P80H84,
|
||||
|
|
@ -1566,6 +1569,144 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Yoga Book 9 14IAH10 descriptor fixup.
|
||||
*
|
||||
* The device includes a HID_DG_TOUCHPAD application collection designed for
|
||||
* the Windows inbox HID driver's Win8 PTP touchpad mode. On Linux we want
|
||||
* only the HID_DG_TOUCHSCREEN collections. The touchpad collection (and the
|
||||
* HID_DG_BUTTONTYPE and Win8 compliance blob features it contains) must be
|
||||
* removed so hid-multitouch does not misclassify the touchscreen nodes as
|
||||
* indirect buttonpads.
|
||||
*
|
||||
* The firmware also resets if any USB control request is received while the
|
||||
* CDC-ACM interface is initialising (~1.18 s after enumeration). Dropping
|
||||
* the Win8 blob and Contact Count Max feature reports prevents the
|
||||
* GET_REPORT calls that hid-multitouch issues at probe.
|
||||
*/
|
||||
static void mt_yogabook9_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int *size)
|
||||
{
|
||||
/* Usage Page (Digitizer), Usage (Touch Pad), Collection (Application) */
|
||||
static const __u8 tp_app_hdr[] = { 0x05, 0x0d, 0x09, 0x05, 0xa1, 0x01 };
|
||||
/* Vendor Usage Page 0xff00 (Win8 compliance blob header) */
|
||||
static const __u8 win8_page[] = { 0x06, 0x00, 0xff };
|
||||
/* Usage (Contact Count Max = 0x55) */
|
||||
static const __u8 ccmax_usage[] = { 0x09, 0x55 };
|
||||
unsigned int i;
|
||||
|
||||
/*
|
||||
* Step 1: find and remove the Touch Pad application collection.
|
||||
* Walk HID short items from the collection header to its matching
|
||||
* End Collection, then close the gap with memmove.
|
||||
*/
|
||||
for (i = 0; i + sizeof(tp_app_hdr) <= *size; i++) {
|
||||
if (memcmp(rdesc + i, tp_app_hdr, sizeof(tp_app_hdr)) == 0) {
|
||||
__u8 *start = rdesc + i;
|
||||
__u8 *coll_end = NULL;
|
||||
__u8 *p = start;
|
||||
unsigned int drop;
|
||||
int depth = 0;
|
||||
|
||||
while (p < rdesc + *size) {
|
||||
__u8 b = *p;
|
||||
int ds = b & 3;
|
||||
int item_len;
|
||||
|
||||
if (b == 0xfe) { /* long item */
|
||||
if (p + 2 >= rdesc + *size)
|
||||
break;
|
||||
item_len = p[1] + 3;
|
||||
} else {
|
||||
item_len = (ds == 3) ? 5 : ds + 1;
|
||||
}
|
||||
if (p + item_len > rdesc + *size)
|
||||
break;
|
||||
|
||||
if ((b & 0xfc) == 0xa0)
|
||||
depth++; /* Collection */
|
||||
else if (b == 0xc0) {
|
||||
depth--; /* End Collection */
|
||||
if (depth == 0) {
|
||||
coll_end = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p += item_len;
|
||||
}
|
||||
|
||||
if (!coll_end) {
|
||||
hid_err(hdev,
|
||||
"Yoga Book 9: Touch Pad End Collection not found\n");
|
||||
break;
|
||||
}
|
||||
|
||||
drop = coll_end - start + 1;
|
||||
memmove(start, coll_end + 1, rdesc + *size - coll_end - 1);
|
||||
*size -= drop;
|
||||
hid_dbg(hdev,
|
||||
"Yoga Book 9: dropped Touch Pad collection (%u bytes)\n",
|
||||
drop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 2: neutralize Win8 compliance blob feature reports remaining
|
||||
* in the touchscreen collections. Change Usage Page 0xff00 to 0x0f00
|
||||
* so the case 0xff0000c5 branch in mt_feature_mapping() is not reached
|
||||
* and no GET_REPORT is issued.
|
||||
*/
|
||||
for (i = 0; i + sizeof(win8_page) <= *size; i++) {
|
||||
if (memcmp(rdesc + i, win8_page, sizeof(win8_page)) == 0) {
|
||||
rdesc[i + 2] = 0x0f; /* 0xff00 -> 0x0f00 */
|
||||
hid_dbg(hdev,
|
||||
"Yoga Book 9: neutralized Win8 blob at offset %u\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 3: neutralize Contact Count Max feature reports. Change usage
|
||||
* 0x55 (HID_DG_CONTACTMAX) to 0x00 so mt_feature_mapping() does not
|
||||
* issue GET_REPORT. The class maxcontacts field provides the value.
|
||||
*/
|
||||
for (i = 0; i + sizeof(ccmax_usage) <= *size; i++) {
|
||||
if (memcmp(rdesc + i, ccmax_usage, sizeof(ccmax_usage)) == 0) {
|
||||
rdesc[i + 1] = 0x00;
|
||||
hid_dbg(hdev,
|
||||
"Yoga Book 9: neutralized ContactMax at offset %u\n",
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step 4: neutralize Surface Switch (0x57) and Button Switch (0x58)
|
||||
* feature report usages in the Device Configuration collection.
|
||||
* mt_set_modes() issues HID_REQ_SET_REPORT for these on every
|
||||
* input-device open/close; those repeated control requests hit the
|
||||
* firmware's CDC-ACM init window and trigger resets.
|
||||
*
|
||||
* Input Mode (0x52) is intentionally left intact. mt_set_modes()
|
||||
* sends it once at probe to set the device into touchscreen mode,
|
||||
* which flushes the firmware's contact buffer and clears a persistent
|
||||
* ghost contact (cid 2, fixed coordinates) that otherwise appears on
|
||||
* every enumeration. By probe time cdc_acm has already satisfied the
|
||||
* CDC-ACM init watchdog (~130 ms), so the single SET_REPORT for Input
|
||||
* Mode arrives safely after the reset window has closed.
|
||||
*/
|
||||
for (i = 0; i + 2 <= *size; i++) {
|
||||
if (rdesc[i] == 0x09 &&
|
||||
(rdesc[i + 1] == 0x57 ||
|
||||
rdesc[i + 1] == 0x58)) {
|
||||
hid_dbg(hdev,
|
||||
"Yoga Book 9: neutralized set-modes usage 0x%02x at offset %u\n",
|
||||
rdesc[i + 1], i);
|
||||
rdesc[i + 1] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
unsigned int *size)
|
||||
{
|
||||
|
|
@ -1595,6 +1736,10 @@ got: %x\n",
|
|||
}
|
||||
}
|
||||
|
||||
if (hdev->vendor == USB_VENDOR_ID_LENOVO &&
|
||||
hdev->product == USB_DEVICE_ID_LENOVO_YOGABOOK9I)
|
||||
mt_yogabook9_fixup(hdev, rdesc, size);
|
||||
|
||||
return rdesc;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user