diff options
author | Henrik Rydberg <rydberg@euromail.se> | 2012-09-01 14:11:34 -0400 |
---|---|---|
committer | Henrik Rydberg <rydberg@euromail.se> | 2012-09-19 13:50:20 -0400 |
commit | 76f5902aebdabcac5b1c34b8d9a238bad397364f (patch) | |
tree | 9d8aa7531ceff493700d59ae988fa9545b3029cd /drivers/hid/hid-multitouch.c | |
parent | 7e55bdedfa4a72baa0d4fec8d0948cb65342a9a0 (diff) |
HID: hid-multitouch: Simplify setup and frame synchronization
With the input_configured() callback in place, the setup and frame
synchronization can be simplified. The input device initialization is
moved to mt_input_configured(), to make sure the full HID report has been
seen.
Reviewed-and-tested-by: Benjamin Tissoires <benjamin.tissoires@enac.fr>
Acked-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Henrik Rydberg <rydberg@euromail.se>
Diffstat (limited to 'drivers/hid/hid-multitouch.c')
-rw-r--r-- | drivers/hid/hid-multitouch.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index c400d9008774..1df86a7536b8 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -92,8 +92,10 @@ struct mt_device { | |||
92 | __u8 touches_by_report; /* how many touches are present in one report: | 92 | __u8 touches_by_report; /* how many touches are present in one report: |
93 | * 1 means we should use a serial protocol | 93 | * 1 means we should use a serial protocol |
94 | * > 1 means hybrid (multitouch) protocol */ | 94 | * > 1 means hybrid (multitouch) protocol */ |
95 | bool serial_maybe; /* need to check for serial protocol */ | ||
95 | bool curvalid; /* is the current contact valid? */ | 96 | bool curvalid; /* is the current contact valid? */ |
96 | struct mt_slot *slots; | 97 | struct mt_slot *slots; |
98 | unsigned mt_flags; /* flags to pass to input-mt */ | ||
97 | }; | 99 | }; |
98 | 100 | ||
99 | /* classes of device behavior */ | 101 | /* classes of device behavior */ |
@@ -319,24 +321,16 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
319 | * We need to ignore fields that belong to other collections | 321 | * We need to ignore fields that belong to other collections |
320 | * such as Mouse that might have the same GenericDesktop usages. */ | 322 | * such as Mouse that might have the same GenericDesktop usages. */ |
321 | if (field->application == HID_DG_TOUCHSCREEN) | 323 | if (field->application == HID_DG_TOUCHSCREEN) |
322 | set_bit(INPUT_PROP_DIRECT, hi->input->propbit); | 324 | td->mt_flags |= INPUT_MT_DIRECT; |
323 | else if (field->application != HID_DG_TOUCHPAD) | 325 | else if (field->application != HID_DG_TOUCHPAD) |
324 | return 0; | 326 | return 0; |
325 | 327 | ||
326 | /* In case of an indirect device (touchpad), we need to add | 328 | /* |
327 | * specific BTN_TOOL_* to be handled by the synaptics xorg | 329 | * Model touchscreens providing buttons as touchpads. |
328 | * driver. | ||
329 | * We also consider that touchscreens providing buttons are touchpads. | ||
330 | */ | 330 | */ |
331 | if (field->application == HID_DG_TOUCHPAD || | 331 | if (field->application == HID_DG_TOUCHPAD || |
332 | (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON || | 332 | (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON) |
333 | cls->is_indirect) { | 333 | td->mt_flags |= INPUT_MT_POINTER; |
334 | set_bit(INPUT_PROP_POINTER, hi->input->propbit); | ||
335 | set_bit(BTN_TOOL_FINGER, hi->input->keybit); | ||
336 | set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit); | ||
337 | set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit); | ||
338 | set_bit(BTN_TOOL_QUADTAP, hi->input->keybit); | ||
339 | } | ||
340 | 334 | ||
341 | /* eGalax devices provide a Digitizer.Stylus input which overrides | 335 | /* eGalax devices provide a Digitizer.Stylus input which overrides |
342 | * the correct Digitizers.Finger X/Y ranges. | 336 | * the correct Digitizers.Finger X/Y ranges. |
@@ -353,8 +347,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
353 | EV_ABS, ABS_MT_POSITION_X); | 347 | EV_ABS, ABS_MT_POSITION_X); |
354 | set_abs(hi->input, ABS_MT_POSITION_X, field, | 348 | set_abs(hi->input, ABS_MT_POSITION_X, field, |
355 | cls->sn_move); | 349 | cls->sn_move); |
356 | /* touchscreen emulation */ | ||
357 | set_abs(hi->input, ABS_X, field, cls->sn_move); | ||
358 | mt_store_field(usage, td, hi); | 350 | mt_store_field(usage, td, hi); |
359 | td->last_field_index = field->index; | 351 | td->last_field_index = field->index; |
360 | return 1; | 352 | return 1; |
@@ -363,8 +355,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
363 | EV_ABS, ABS_MT_POSITION_Y); | 355 | EV_ABS, ABS_MT_POSITION_Y); |
364 | set_abs(hi->input, ABS_MT_POSITION_Y, field, | 356 | set_abs(hi->input, ABS_MT_POSITION_Y, field, |
365 | cls->sn_move); | 357 | cls->sn_move); |
366 | /* touchscreen emulation */ | ||
367 | set_abs(hi->input, ABS_Y, field, cls->sn_move); | ||
368 | mt_store_field(usage, td, hi); | 358 | mt_store_field(usage, td, hi); |
369 | td->last_field_index = field->index; | 359 | td->last_field_index = field->index; |
370 | return 1; | 360 | return 1; |
@@ -388,9 +378,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
388 | td->last_field_index = field->index; | 378 | td->last_field_index = field->index; |
389 | return 1; | 379 | return 1; |
390 | case HID_DG_CONTACTID: | 380 | case HID_DG_CONTACTID: |
391 | if (!td->maxcontacts) | ||
392 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | ||
393 | input_mt_init_slots(hi->input, td->maxcontacts, 0); | ||
394 | mt_store_field(usage, td, hi); | 381 | mt_store_field(usage, td, hi); |
395 | td->last_field_index = field->index; | 382 | td->last_field_index = field->index; |
396 | td->touches_by_report++; | 383 | td->touches_by_report++; |
@@ -418,9 +405,6 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
418 | EV_ABS, ABS_MT_PRESSURE); | 405 | EV_ABS, ABS_MT_PRESSURE); |
419 | set_abs(hi->input, ABS_MT_PRESSURE, field, | 406 | set_abs(hi->input, ABS_MT_PRESSURE, field, |
420 | cls->sn_pressure); | 407 | cls->sn_pressure); |
421 | /* touchscreen emulation */ | ||
422 | set_abs(hi->input, ABS_PRESSURE, field, | ||
423 | cls->sn_pressure); | ||
424 | mt_store_field(usage, td, hi); | 408 | mt_store_field(usage, td, hi); |
425 | td->last_field_index = field->index; | 409 | td->last_field_index = field->index; |
426 | return 1; | 410 | return 1; |
@@ -536,7 +520,7 @@ static void mt_emit_event(struct mt_device *td, struct input_dev *input) | |||
536 | 520 | ||
537 | } | 521 | } |
538 | 522 | ||
539 | input_mt_report_pointer_emulation(input, true); | 523 | input_mt_sync_frame(input); |
540 | input_sync(input); | 524 | input_sync(input); |
541 | td->num_received = 0; | 525 | td->num_received = 0; |
542 | } | 526 | } |
@@ -685,6 +669,32 @@ static void mt_post_parse(struct mt_device *td) | |||
685 | } | 669 | } |
686 | } | 670 | } |
687 | 671 | ||
672 | static void mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | ||
673 | |||
674 | { | ||
675 | struct mt_device *td = hid_get_drvdata(hdev); | ||
676 | struct mt_class *cls = &td->mtclass; | ||
677 | struct input_dev *input = hi->input; | ||
678 | |||
679 | /* Only initialize slots for MT input devices */ | ||
680 | if (!test_bit(ABS_MT_POSITION_X, input->absbit)) | ||
681 | return; | ||
682 | |||
683 | if (!td->maxcontacts) | ||
684 | td->maxcontacts = MT_DEFAULT_MAXCONTACT; | ||
685 | |||
686 | mt_post_parse(td); | ||
687 | if (td->serial_maybe) | ||
688 | mt_post_parse_default_settings(td); | ||
689 | |||
690 | if (cls->is_indirect) | ||
691 | td->mt_flags |= INPUT_MT_POINTER; | ||
692 | |||
693 | input_mt_init_slots(input, td->maxcontacts, td->mt_flags); | ||
694 | |||
695 | td->mt_flags = 0; | ||
696 | } | ||
697 | |||
688 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | 698 | static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) |
689 | { | 699 | { |
690 | int ret, i; | 700 | int ret, i; |
@@ -722,6 +732,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
722 | goto fail; | 732 | goto fail; |
723 | } | 733 | } |
724 | 734 | ||
735 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) | ||
736 | td->serial_maybe = true; | ||
737 | |||
725 | ret = hid_parse(hdev); | 738 | ret = hid_parse(hdev); |
726 | if (ret != 0) | 739 | if (ret != 0) |
727 | goto fail; | 740 | goto fail; |
@@ -730,11 +743,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
730 | if (ret) | 743 | if (ret) |
731 | goto fail; | 744 | goto fail; |
732 | 745 | ||
733 | mt_post_parse(td); | ||
734 | |||
735 | if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) | ||
736 | mt_post_parse_default_settings(td); | ||
737 | |||
738 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), | 746 | td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), |
739 | GFP_KERNEL); | 747 | GFP_KERNEL); |
740 | if (!td->slots) { | 748 | if (!td->slots) { |
@@ -1087,6 +1095,7 @@ static struct hid_driver mt_driver = { | |||
1087 | .remove = mt_remove, | 1095 | .remove = mt_remove, |
1088 | .input_mapping = mt_input_mapping, | 1096 | .input_mapping = mt_input_mapping, |
1089 | .input_mapped = mt_input_mapped, | 1097 | .input_mapped = mt_input_mapped, |
1098 | .input_configured = mt_input_configured, | ||
1090 | .feature_mapping = mt_feature_mapping, | 1099 | .feature_mapping = mt_feature_mapping, |
1091 | .usage_table = mt_grabbed_usages, | 1100 | .usage_table = mt_grabbed_usages, |
1092 | .event = mt_event, | 1101 | .event = mt_event, |