Skip to content

Commit ed9d5c9

Browse files
Benjamin TissoiresJiri Kosina
Benjamin Tissoires
authored and
Jiri Kosina
committed
HID: multitouch: fix handling of buggy reports descriptors for Dell ST2220T
LG multitouch panels, such as the one found in Dell ST2220T, has buggy reports descriptors. With the previous implementation, it was impossible to rely on the reports descriptors to determine how the different touches are emitted from the device. This patch changes the splitting of the different touches in the report in a more robust way. Signed-off-by: Benjamin Tissoires <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 2ce09df commit ed9d5c9

File tree

1 file changed

+25
-39
lines changed

1 file changed

+25
-39
lines changed

drivers/hid/hid-multitouch.c

Lines changed: 25 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ struct mt_device {
7575
struct mt_class mtclass; /* our mt device class */
7676
unsigned last_field_index; /* last field index of the report */
7777
unsigned last_slot_field; /* the last field of a slot */
78-
int last_mt_collection; /* last known mt-related collection */
7978
__s8 inputmode; /* InputMode HID feature, -1 if non-existent */
8079
__s8 maxcontact_report_id; /* Maximum Contact Number HID feature,
8180
-1 if non-existent */
@@ -273,6 +272,13 @@ static void set_abs(struct input_dev *input, unsigned int code,
273272
input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
274273
}
275274

275+
static void set_last_slot_field(struct hid_usage *usage, struct mt_device *td,
276+
struct hid_input *hi)
277+
{
278+
if (!test_bit(usage->hid, hi->input->absbit))
279+
td->last_slot_field = usage->hid;
280+
}
281+
276282
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
277283
struct hid_field *field, struct hid_usage *usage,
278284
unsigned long **bit, int *max)
@@ -321,10 +327,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
321327
cls->sn_move);
322328
/* touchscreen emulation */
323329
set_abs(hi->input, ABS_X, field, cls->sn_move);
324-
if (td->last_mt_collection == usage->collection_index) {
325-
td->last_slot_field = usage->hid;
326-
td->last_field_index = field->index;
327-
}
330+
set_last_slot_field(usage, td, hi);
331+
td->last_field_index = field->index;
328332
return 1;
329333
case HID_GD_Y:
330334
hid_map_usage(hi, usage, bit, max,
@@ -333,53 +337,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
333337
cls->sn_move);
334338
/* touchscreen emulation */
335339
set_abs(hi->input, ABS_Y, field, cls->sn_move);
336-
if (td->last_mt_collection == usage->collection_index) {
337-
td->last_slot_field = usage->hid;
338-
td->last_field_index = field->index;
339-
}
340+
set_last_slot_field(usage, td, hi);
341+
td->last_field_index = field->index;
340342
return 1;
341343
}
342344
return 0;
343345

344346
case HID_UP_DIGITIZER:
345347
switch (usage->hid) {
346348
case HID_DG_INRANGE:
347-
if (td->last_mt_collection == usage->collection_index) {
348-
td->last_slot_field = usage->hid;
349-
td->last_field_index = field->index;
350-
}
349+
set_last_slot_field(usage, td, hi);
350+
td->last_field_index = field->index;
351351
return 1;
352352
case HID_DG_CONFIDENCE:
353-
if (td->last_mt_collection == usage->collection_index) {
354-
td->last_slot_field = usage->hid;
355-
td->last_field_index = field->index;
356-
}
353+
set_last_slot_field(usage, td, hi);
354+
td->last_field_index = field->index;
357355
return 1;
358356
case HID_DG_TIPSWITCH:
359357
hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
360358
input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
361-
if (td->last_mt_collection == usage->collection_index) {
362-
td->last_slot_field = usage->hid;
363-
td->last_field_index = field->index;
364-
}
359+
set_last_slot_field(usage, td, hi);
360+
td->last_field_index = field->index;
365361
return 1;
366362
case HID_DG_CONTACTID:
367363
if (!td->maxcontacts)
368364
td->maxcontacts = MT_DEFAULT_MAXCONTACT;
369365
input_mt_init_slots(hi->input, td->maxcontacts);
370366
td->last_slot_field = usage->hid;
371367
td->last_field_index = field->index;
372-
td->last_mt_collection = usage->collection_index;
373368
return 1;
374369
case HID_DG_WIDTH:
375370
hid_map_usage(hi, usage, bit, max,
376371
EV_ABS, ABS_MT_TOUCH_MAJOR);
377372
set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
378373
cls->sn_width);
379-
if (td->last_mt_collection == usage->collection_index) {
380-
td->last_slot_field = usage->hid;
381-
td->last_field_index = field->index;
382-
}
374+
set_last_slot_field(usage, td, hi);
375+
td->last_field_index = field->index;
383376
return 1;
384377
case HID_DG_HEIGHT:
385378
hid_map_usage(hi, usage, bit, max,
@@ -388,10 +381,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
388381
cls->sn_height);
389382
input_set_abs_params(hi->input,
390383
ABS_MT_ORIENTATION, 0, 1, 0, 0);
391-
if (td->last_mt_collection == usage->collection_index) {
392-
td->last_slot_field = usage->hid;
393-
td->last_field_index = field->index;
394-
}
384+
set_last_slot_field(usage, td, hi);
385+
td->last_field_index = field->index;
395386
return 1;
396387
case HID_DG_TIPPRESSURE:
397388
hid_map_usage(hi, usage, bit, max,
@@ -401,20 +392,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
401392
/* touchscreen emulation */
402393
set_abs(hi->input, ABS_PRESSURE, field,
403394
cls->sn_pressure);
404-
if (td->last_mt_collection == usage->collection_index) {
405-
td->last_slot_field = usage->hid;
406-
td->last_field_index = field->index;
407-
}
395+
set_last_slot_field(usage, td, hi);
396+
td->last_field_index = field->index;
408397
return 1;
409398
case HID_DG_CONTACTCOUNT:
410-
if (td->last_mt_collection == usage->collection_index)
411-
td->last_field_index = field->index;
399+
td->last_field_index = field->index;
412400
return 1;
413401
case HID_DG_CONTACTMAX:
414402
/* we don't set td->last_slot_field as contactcount and
415403
* contact max are global to the report */
416-
if (td->last_mt_collection == usage->collection_index)
417-
td->last_field_index = field->index;
404+
td->last_field_index = field->index;
418405
return -1;
419406
}
420407
case HID_DG_TOUCH:
@@ -670,7 +657,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
670657
td->mtclass = *mtclass;
671658
td->inputmode = -1;
672659
td->maxcontact_report_id = -1;
673-
td->last_mt_collection = -1;
674660
hid_set_drvdata(hdev, td);
675661

676662
ret = hid_parse(hdev);

0 commit comments

Comments
 (0)