aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-multitouch.c
diff options
context:
space:
mode:
authorBenjamin Tissoires <benjamin.tissoires@enac.fr>2012-03-06 11:57:03 -0500
committerJiri Kosina <jkosina@suse.cz>2012-03-12 06:23:55 -0400
commited9d5c96147b3bed6178252e8e04b27b7d32edd0 (patch)
treefa779d1f7d4ffd4f823de441de09464b5752f51e /drivers/hid/hid-multitouch.c
parent2ce09df47b67f16367272f63f85f4cc991e6009a (diff)
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 <benjamin.tissoires@gmail.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r--drivers/hid/hid-multitouch.c64
1 files changed, 25 insertions, 39 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 019de83def6..2088ab4e5db 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -75,7 +75,6 @@ struct mt_device {
75 struct mt_class mtclass; /* our mt device class */ 75 struct mt_class mtclass; /* our mt device class */
76 unsigned last_field_index; /* last field index of the report */ 76 unsigned last_field_index; /* last field index of the report */
77 unsigned last_slot_field; /* the last field of a slot */ 77 unsigned last_slot_field; /* the last field of a slot */
78 int last_mt_collection; /* last known mt-related collection */
79 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ 78 __s8 inputmode; /* InputMode HID feature, -1 if non-existent */
80 __s8 maxcontact_report_id; /* Maximum Contact Number HID feature, 79 __s8 maxcontact_report_id; /* Maximum Contact Number HID feature,
81 -1 if non-existent */ 80 -1 if non-existent */
@@ -273,6 +272,13 @@ static void set_abs(struct input_dev *input, unsigned int code,
273 input_set_abs_params(input, code, fmin, fmax, fuzz, 0); 272 input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
274} 273}
275 274
275static 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
276static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, 282static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
277 struct hid_field *field, struct hid_usage *usage, 283 struct hid_field *field, struct hid_usage *usage,
278 unsigned long **bit, int *max) 284 unsigned long **bit, int *max)
@@ -321,10 +327,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
321 cls->sn_move); 327 cls->sn_move);
322 /* touchscreen emulation */ 328 /* touchscreen emulation */
323 set_abs(hi->input, ABS_X, field, cls->sn_move); 329 set_abs(hi->input, ABS_X, field, cls->sn_move);
324 if (td->last_mt_collection == usage->collection_index) { 330 set_last_slot_field(usage, td, hi);
325 td->last_slot_field = usage->hid; 331 td->last_field_index = field->index;
326 td->last_field_index = field->index;
327 }
328 return 1; 332 return 1;
329 case HID_GD_Y: 333 case HID_GD_Y:
330 hid_map_usage(hi, usage, bit, max, 334 hid_map_usage(hi, usage, bit, max,
@@ -333,10 +337,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
333 cls->sn_move); 337 cls->sn_move);
334 /* touchscreen emulation */ 338 /* touchscreen emulation */
335 set_abs(hi->input, ABS_Y, field, cls->sn_move); 339 set_abs(hi->input, ABS_Y, field, cls->sn_move);
336 if (td->last_mt_collection == usage->collection_index) { 340 set_last_slot_field(usage, td, hi);
337 td->last_slot_field = usage->hid; 341 td->last_field_index = field->index;
338 td->last_field_index = field->index;
339 }
340 return 1; 342 return 1;
341 } 343 }
342 return 0; 344 return 0;
@@ -344,24 +346,18 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
344 case HID_UP_DIGITIZER: 346 case HID_UP_DIGITIZER:
345 switch (usage->hid) { 347 switch (usage->hid) {
346 case HID_DG_INRANGE: 348 case HID_DG_INRANGE:
347 if (td->last_mt_collection == usage->collection_index) { 349 set_last_slot_field(usage, td, hi);
348 td->last_slot_field = usage->hid; 350 td->last_field_index = field->index;
349 td->last_field_index = field->index;
350 }
351 return 1; 351 return 1;
352 case HID_DG_CONFIDENCE: 352 case HID_DG_CONFIDENCE:
353 if (td->last_mt_collection == usage->collection_index) { 353 set_last_slot_field(usage, td, hi);
354 td->last_slot_field = usage->hid; 354 td->last_field_index = field->index;
355 td->last_field_index = field->index;
356 }
357 return 1; 355 return 1;
358 case HID_DG_TIPSWITCH: 356 case HID_DG_TIPSWITCH:
359 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); 357 hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
360 input_set_capability(hi->input, EV_KEY, BTN_TOUCH); 358 input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
361 if (td->last_mt_collection == usage->collection_index) { 359 set_last_slot_field(usage, td, hi);
362 td->last_slot_field = usage->hid; 360 td->last_field_index = field->index;
363 td->last_field_index = field->index;
364 }
365 return 1; 361 return 1;
366 case HID_DG_CONTACTID: 362 case HID_DG_CONTACTID:
367 if (!td->maxcontacts) 363 if (!td->maxcontacts)
@@ -369,17 +365,14 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
369 input_mt_init_slots(hi->input, td->maxcontacts); 365 input_mt_init_slots(hi->input, td->maxcontacts);
370 td->last_slot_field = usage->hid; 366 td->last_slot_field = usage->hid;
371 td->last_field_index = field->index; 367 td->last_field_index = field->index;
372 td->last_mt_collection = usage->collection_index;
373 return 1; 368 return 1;
374 case HID_DG_WIDTH: 369 case HID_DG_WIDTH:
375 hid_map_usage(hi, usage, bit, max, 370 hid_map_usage(hi, usage, bit, max,
376 EV_ABS, ABS_MT_TOUCH_MAJOR); 371 EV_ABS, ABS_MT_TOUCH_MAJOR);
377 set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, 372 set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
378 cls->sn_width); 373 cls->sn_width);
379 if (td->last_mt_collection == usage->collection_index) { 374 set_last_slot_field(usage, td, hi);
380 td->last_slot_field = usage->hid; 375 td->last_field_index = field->index;
381 td->last_field_index = field->index;
382 }
383 return 1; 376 return 1;
384 case HID_DG_HEIGHT: 377 case HID_DG_HEIGHT:
385 hid_map_usage(hi, usage, bit, max, 378 hid_map_usage(hi, usage, bit, max,
@@ -388,10 +381,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
388 cls->sn_height); 381 cls->sn_height);
389 input_set_abs_params(hi->input, 382 input_set_abs_params(hi->input,
390 ABS_MT_ORIENTATION, 0, 1, 0, 0); 383 ABS_MT_ORIENTATION, 0, 1, 0, 0);
391 if (td->last_mt_collection == usage->collection_index) { 384 set_last_slot_field(usage, td, hi);
392 td->last_slot_field = usage->hid; 385 td->last_field_index = field->index;
393 td->last_field_index = field->index;
394 }
395 return 1; 386 return 1;
396 case HID_DG_TIPPRESSURE: 387 case HID_DG_TIPPRESSURE:
397 hid_map_usage(hi, usage, bit, max, 388 hid_map_usage(hi, usage, bit, max,
@@ -401,20 +392,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
401 /* touchscreen emulation */ 392 /* touchscreen emulation */
402 set_abs(hi->input, ABS_PRESSURE, field, 393 set_abs(hi->input, ABS_PRESSURE, field,
403 cls->sn_pressure); 394 cls->sn_pressure);
404 if (td->last_mt_collection == usage->collection_index) { 395 set_last_slot_field(usage, td, hi);
405 td->last_slot_field = usage->hid; 396 td->last_field_index = field->index;
406 td->last_field_index = field->index;
407 }
408 return 1; 397 return 1;
409 case HID_DG_CONTACTCOUNT: 398 case HID_DG_CONTACTCOUNT:
410 if (td->last_mt_collection == usage->collection_index) 399 td->last_field_index = field->index;
411 td->last_field_index = field->index;
412 return 1; 400 return 1;
413 case HID_DG_CONTACTMAX: 401 case HID_DG_CONTACTMAX:
414 /* we don't set td->last_slot_field as contactcount and 402 /* we don't set td->last_slot_field as contactcount and
415 * contact max are global to the report */ 403 * contact max are global to the report */
416 if (td->last_mt_collection == usage->collection_index) 404 td->last_field_index = field->index;
417 td->last_field_index = field->index;
418 return -1; 405 return -1;
419 } 406 }
420 case HID_DG_TOUCH: 407 case HID_DG_TOUCH:
@@ -670,7 +657,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
670 td->mtclass = *mtclass; 657 td->mtclass = *mtclass;
671 td->inputmode = -1; 658 td->inputmode = -1;
672 td->maxcontact_report_id = -1; 659 td->maxcontact_report_id = -1;
673 td->last_mt_collection = -1;
674 hid_set_drvdata(hdev, td); 660 hid_set_drvdata(hdev, td);
675 661
676 ret = hid_parse(hdev); 662 ret = hid_parse(hdev);