diff options
| author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2018-07-13 10:13:47 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2018-07-17 09:33:47 -0400 |
| commit | 8dfe14b3b47ff832cb638731f9fc696a3a84f804 (patch) | |
| tree | 8e4d1d1f80e006389b39a634e1939c9d6121babc /drivers/hid | |
| parent | 3ceb3826448d1ec4650a6c2b62baa9e0994ac7d3 (diff) | |
HID: multitouch: ditch mt_report_id
Now that the driver can handle more than one multitouch collection in
a single HID device, ditch the last bit that contains us to use only
one mt collection.
Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid')
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 126 |
1 files changed, 94 insertions, 32 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index beaac36f61a7..a2c10fc62ef2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -147,6 +147,13 @@ struct mt_fields { | |||
| 147 | unsigned int length; | 147 | unsigned int length; |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | struct mt_report_data { | ||
| 151 | struct list_head list; | ||
| 152 | struct hid_report *report; | ||
| 153 | struct mt_application *application; | ||
| 154 | bool is_mt_collection; | ||
| 155 | }; | ||
| 156 | |||
| 150 | struct mt_device { | 157 | struct mt_device { |
| 151 | struct mt_class mtclass; /* our mt device class */ | 158 | struct mt_class mtclass; /* our mt device class */ |
| 152 | struct timer_list release_timer; /* to release sticky fingers */ | 159 | struct timer_list release_timer; /* to release sticky fingers */ |
| @@ -154,13 +161,13 @@ struct mt_device { | |||
| 154 | struct mt_fields *fields; /* temporary placeholder for storing the | 161 | struct mt_fields *fields; /* temporary placeholder for storing the |
| 155 | multitouch fields */ | 162 | multitouch fields */ |
| 156 | unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ | 163 | unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ |
| 157 | unsigned mt_report_id; /* the report ID of the multitouch device */ | ||
| 158 | __u8 inputmode_value; /* InputMode HID feature value */ | 164 | __u8 inputmode_value; /* InputMode HID feature value */ |
| 159 | __u8 maxcontacts; | 165 | __u8 maxcontacts; |
| 160 | bool is_buttonpad; /* is this device a button pad? */ | 166 | bool is_buttonpad; /* is this device a button pad? */ |
| 161 | bool serial_maybe; /* need to check for serial protocol */ | 167 | bool serial_maybe; /* need to check for serial protocol */ |
| 162 | 168 | ||
| 163 | struct list_head applications; | 169 | struct list_head applications; |
| 170 | struct list_head reports; | ||
| 164 | }; | 171 | }; |
| 165 | 172 | ||
| 166 | static void mt_post_parse_default_settings(struct mt_device *td, | 173 | static void mt_post_parse_default_settings(struct mt_device *td, |
| @@ -526,6 +533,60 @@ static struct mt_application *mt_find_application(struct mt_device *td, | |||
| 526 | return mt_application; | 533 | return mt_application; |
| 527 | } | 534 | } |
| 528 | 535 | ||
| 536 | static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, | ||
| 537 | struct hid_report *report) | ||
| 538 | { | ||
| 539 | struct mt_report_data *rdata; | ||
| 540 | struct hid_field *field; | ||
| 541 | int r, n; | ||
| 542 | |||
| 543 | rdata = devm_kzalloc(&td->hdev->dev, sizeof(*rdata), GFP_KERNEL); | ||
| 544 | if (!rdata) | ||
| 545 | return NULL; | ||
| 546 | |||
| 547 | rdata->report = report; | ||
| 548 | rdata->application = mt_find_application(td, report->application); | ||
| 549 | |||
| 550 | if (!rdata->application) { | ||
| 551 | devm_kfree(&td->hdev->dev, rdata); | ||
| 552 | return NULL; | ||
| 553 | } | ||
| 554 | |||
| 555 | for (r = 0; r < report->maxfield; r++) { | ||
| 556 | field = report->field[r]; | ||
| 557 | |||
| 558 | if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) | ||
| 559 | continue; | ||
| 560 | |||
| 561 | for (n = 0; n < field->report_count; n++) { | ||
| 562 | if (field->usage[n].hid == HID_DG_CONTACTID) | ||
| 563 | rdata->is_mt_collection = true; | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 567 | list_add_tail(&rdata->list, &td->reports); | ||
| 568 | |||
| 569 | return rdata; | ||
| 570 | } | ||
| 571 | |||
| 572 | static struct mt_report_data *mt_find_report_data(struct mt_device *td, | ||
| 573 | struct hid_report *report) | ||
| 574 | { | ||
| 575 | struct mt_report_data *tmp, *rdata = NULL; | ||
| 576 | |||
| 577 | list_for_each_entry(tmp, &td->reports, list) { | ||
| 578 | if (report == tmp->report) { | ||
| 579 | rdata = tmp; | ||
| 580 | break; | ||
| 581 | } | ||
| 582 | } | ||
| 583 | |||
| 584 | if (!rdata) | ||
| 585 | rdata = mt_allocate_report_data(td, report); | ||
| 586 | |||
| 587 | return rdata; | ||
| 588 | } | ||
| 589 | |||
| 529 | static void mt_store_field(struct hid_usage *usage, struct mt_device *td, | 590 | static void mt_store_field(struct hid_usage *usage, struct mt_device *td, |
| 530 | struct hid_input *hi) | 591 | struct hid_input *hi) |
| 531 | { | 592 | { |
| @@ -614,7 +675,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 614 | case HID_DG_CONTACTID: | 675 | case HID_DG_CONTACTID: |
| 615 | mt_store_field(usage, td, hi); | 676 | mt_store_field(usage, td, hi); |
| 616 | app->touches_by_report++; | 677 | app->touches_by_report++; |
| 617 | td->mt_report_id = field->report->id; | ||
| 618 | return 1; | 678 | return 1; |
| 619 | case HID_DG_WIDTH: | 679 | case HID_DG_WIDTH: |
| 620 | hid_map_usage(hi, usage, bit, max, | 680 | hid_map_usage(hi, usage, bit, max, |
| @@ -979,10 +1039,12 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | |||
| 979 | } | 1039 | } |
| 980 | } | 1040 | } |
| 981 | 1041 | ||
| 982 | static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | 1042 | static void mt_touch_report(struct hid_device *hid, |
| 1043 | struct mt_report_data *rdata) | ||
| 983 | { | 1044 | { |
| 984 | struct mt_device *td = hid_get_drvdata(hid); | 1045 | struct mt_device *td = hid_get_drvdata(hid); |
| 985 | struct mt_application *app; | 1046 | struct hid_report *report = rdata->report; |
| 1047 | struct mt_application *app = rdata->application; | ||
| 986 | struct hid_field *field; | 1048 | struct hid_field *field; |
| 987 | bool first_packet; | 1049 | bool first_packet; |
| 988 | unsigned count; | 1050 | unsigned count; |
| @@ -994,11 +1056,6 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) | |||
| 994 | if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) | 1056 | if (test_and_set_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags)) |
| 995 | return; | 1057 | return; |
| 996 | 1058 | ||
| 997 | app = mt_find_application(td, report->application); | ||
| 998 | |||
| 999 | if (!app) | ||
| 1000 | return; | ||
| 1001 | |||
| 1002 | /* | 1059 | /* |
| 1003 | * Includes multi-packet support where subsequent | 1060 | * Includes multi-packet support where subsequent |
| 1004 | * packets are sent with zero contactcount. | 1061 | * packets are sent with zero contactcount. |
| @@ -1119,8 +1176,15 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 1119 | { | 1176 | { |
| 1120 | struct mt_device *td = hid_get_drvdata(hdev); | 1177 | struct mt_device *td = hid_get_drvdata(hdev); |
| 1121 | struct mt_application *application; | 1178 | struct mt_application *application; |
| 1179 | struct mt_report_data *rdata; | ||
| 1180 | |||
| 1181 | rdata = mt_find_report_data(td, field->report); | ||
| 1182 | if (!rdata) { | ||
| 1183 | hid_err(hdev, "failed to allocate data for report\n"); | ||
| 1184 | return 0; | ||
| 1185 | } | ||
| 1122 | 1186 | ||
| 1123 | application = mt_find_application(td, field->application); | 1187 | application = rdata->application; |
| 1124 | 1188 | ||
| 1125 | /* | 1189 | /* |
| 1126 | * If mtclass.export_all_inputs is not set, only map fields from | 1190 | * If mtclass.export_all_inputs is not set, only map fields from |
| @@ -1163,22 +1227,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 1163 | return 1; | 1227 | return 1; |
| 1164 | } | 1228 | } |
| 1165 | 1229 | ||
| 1166 | /* | 1230 | if (rdata->is_mt_collection && |
| 1167 | * some egalax touchscreens have "application == HID_DG_TOUCHSCREEN" | 1231 | (field->application == HID_DG_TOUCHSCREEN || |
| 1168 | * for the stylus. | 1232 | field->application == HID_DG_TOUCHPAD)) |
| 1169 | * The check for mt_report_id ensures we don't process | ||
| 1170 | * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical | ||
| 1171 | * collection, but within the report ID. | ||
| 1172 | */ | ||
| 1173 | if (field->physical == HID_DG_STYLUS) | ||
| 1174 | return 0; | ||
| 1175 | else if ((field->physical == 0) && | ||
| 1176 | (field->report->id != td->mt_report_id) && | ||
| 1177 | (td->mt_report_id != -1)) | ||
| 1178 | return 0; | ||
| 1179 | |||
| 1180 | if (field->application == HID_DG_TOUCHSCREEN || | ||
| 1181 | field->application == HID_DG_TOUCHPAD) | ||
| 1182 | return mt_touch_input_mapping(hdev, hi, field, usage, bit, max, | 1233 | return mt_touch_input_mapping(hdev, hi, field, usage, bit, max, |
| 1183 | application); | 1234 | application); |
| 1184 | 1235 | ||
| @@ -1211,8 +1262,10 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, | |||
| 1211 | struct hid_usage *usage, __s32 value) | 1262 | struct hid_usage *usage, __s32 value) |
| 1212 | { | 1263 | { |
| 1213 | struct mt_device *td = hid_get_drvdata(hid); | 1264 | struct mt_device *td = hid_get_drvdata(hid); |
| 1265 | struct mt_report_data *rdata; | ||
| 1214 | 1266 | ||
| 1215 | if (field->report->id == td->mt_report_id) | 1267 | rdata = mt_find_report_data(td, field->report); |
| 1268 | if (rdata && rdata->is_mt_collection) | ||
| 1216 | return mt_touch_event(hid, field, usage, value); | 1269 | return mt_touch_event(hid, field, usage, value); |
| 1217 | 1270 | ||
| 1218 | return 0; | 1271 | return 0; |
| @@ -1222,12 +1275,14 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) | |||
| 1222 | { | 1275 | { |
| 1223 | struct mt_device *td = hid_get_drvdata(hid); | 1276 | struct mt_device *td = hid_get_drvdata(hid); |
| 1224 | struct hid_field *field = report->field[0]; | 1277 | struct hid_field *field = report->field[0]; |
| 1278 | struct mt_report_data *rdata; | ||
| 1225 | 1279 | ||
| 1226 | if (!(hid->claimed & HID_CLAIMED_INPUT)) | 1280 | if (!(hid->claimed & HID_CLAIMED_INPUT)) |
| 1227 | return; | 1281 | return; |
| 1228 | 1282 | ||
| 1229 | if (report->id == td->mt_report_id) | 1283 | rdata = mt_find_report_data(td, report); |
| 1230 | return mt_touch_report(hid, report); | 1284 | if (rdata && rdata->is_mt_collection) |
| 1285 | return mt_touch_report(hid, rdata); | ||
| 1231 | 1286 | ||
| 1232 | if (field && field->hidinput && field->hidinput->input) | 1287 | if (field && field->hidinput && field->hidinput->input) |
| 1233 | input_sync(field->hidinput->input); | 1288 | input_sync(field->hidinput->input); |
| @@ -1368,15 +1423,22 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) | |||
| 1368 | char *name; | 1423 | char *name; |
| 1369 | const char *suffix = NULL; | 1424 | const char *suffix = NULL; |
| 1370 | unsigned int application = 0; | 1425 | unsigned int application = 0; |
| 1426 | struct mt_report_data *rdata; | ||
| 1371 | struct mt_application *mt_application = NULL; | 1427 | struct mt_application *mt_application = NULL; |
| 1372 | struct hid_report *report; | 1428 | struct hid_report *report; |
| 1373 | int ret; | 1429 | int ret; |
| 1374 | 1430 | ||
| 1375 | list_for_each_entry(report, &hi->reports, hidinput_list) { | 1431 | list_for_each_entry(report, &hi->reports, hidinput_list) { |
| 1376 | application = report->application; | 1432 | application = report->application; |
| 1377 | mt_application = mt_find_application(td, application); | 1433 | rdata = mt_find_report_data(td, report); |
| 1434 | if (!rdata) { | ||
| 1435 | hid_err(hdev, "failed to allocate data for report\n"); | ||
| 1436 | return -ENOMEM; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | mt_application = rdata->application; | ||
| 1378 | 1440 | ||
| 1379 | if (report->id == td->mt_report_id) { | 1441 | if (rdata->is_mt_collection) { |
| 1380 | ret = mt_touch_input_configured(hdev, hi, | 1442 | ret = mt_touch_input_configured(hdev, hi, |
| 1381 | mt_application); | 1443 | mt_application); |
| 1382 | if (ret) | 1444 | if (ret) |
| @@ -1529,10 +1591,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1529 | td->hdev = hdev; | 1591 | td->hdev = hdev; |
| 1530 | td->mtclass = *mtclass; | 1592 | td->mtclass = *mtclass; |
| 1531 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; | 1593 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; |
| 1532 | td->mt_report_id = -1; | ||
| 1533 | hid_set_drvdata(hdev, td); | 1594 | hid_set_drvdata(hdev, td); |
| 1534 | 1595 | ||
| 1535 | INIT_LIST_HEAD(&td->applications); | 1596 | INIT_LIST_HEAD(&td->applications); |
| 1597 | INIT_LIST_HEAD(&td->reports); | ||
| 1536 | 1598 | ||
| 1537 | td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), | 1599 | td->fields = devm_kzalloc(&hdev->dev, sizeof(struct mt_fields), |
| 1538 | GFP_KERNEL); | 1600 | GFP_KERNEL); |
