diff options
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 131 |
1 files changed, 60 insertions, 71 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 43784d31a1a3..8878de9eedba 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -127,11 +127,7 @@ struct mt_device { | |||
| 127 | int left_button_state; /* left button state */ | 127 | int left_button_state; /* left button state */ |
| 128 | unsigned last_slot_field; /* the last field of a slot */ | 128 | unsigned last_slot_field; /* the last field of a slot */ |
| 129 | unsigned mt_report_id; /* the report ID of the multitouch device */ | 129 | unsigned mt_report_id; /* the report ID of the multitouch device */ |
| 130 | __s16 inputmode; /* InputMode HID feature, -1 if non-existent */ | 130 | __u8 inputmode_value; /* InputMode HID feature value */ |
| 131 | __s16 inputmode_index; /* InputMode HID feature index in the report */ | ||
| 132 | __s16 maxcontact_report_id; /* Maximum Contact Number HID feature, | ||
| 133 | -1 if non-existent */ | ||
| 134 | __u8 inputmode_value; /* InputMode HID feature value */ | ||
| 135 | __u8 num_received; /* how many contacts we received */ | 131 | __u8 num_received; /* how many contacts we received */ |
| 136 | __u8 num_expected; /* expected last contact index */ | 132 | __u8 num_expected; /* expected last contact index */ |
| 137 | __u8 maxcontacts; | 133 | __u8 maxcontacts; |
| @@ -415,32 +411,9 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 415 | struct mt_device *td = hid_get_drvdata(hdev); | 411 | struct mt_device *td = hid_get_drvdata(hdev); |
| 416 | 412 | ||
| 417 | switch (usage->hid) { | 413 | switch (usage->hid) { |
| 418 | case HID_DG_INPUTMODE: | ||
| 419 | /* Ignore if value index is out of bounds. */ | ||
| 420 | if (usage->usage_index >= field->report_count) { | ||
| 421 | dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); | ||
| 422 | break; | ||
| 423 | } | ||
| 424 | |||
| 425 | if (td->inputmode < 0) { | ||
| 426 | td->inputmode = field->report->id; | ||
| 427 | td->inputmode_index = usage->usage_index; | ||
| 428 | } else { | ||
| 429 | /* | ||
| 430 | * Some elan panels wrongly declare 2 input mode | ||
| 431 | * features, and silently ignore when we set the | ||
| 432 | * value in the second field. Skip the second feature | ||
| 433 | * and hope for the best. | ||
| 434 | */ | ||
| 435 | dev_info(&hdev->dev, | ||
| 436 | "Ignoring the extra HID_DG_INPUTMODE\n"); | ||
| 437 | } | ||
| 438 | |||
| 439 | break; | ||
| 440 | case HID_DG_CONTACTMAX: | 414 | case HID_DG_CONTACTMAX: |
| 441 | mt_get_feature(hdev, field->report); | 415 | mt_get_feature(hdev, field->report); |
| 442 | 416 | ||
| 443 | td->maxcontact_report_id = field->report->id; | ||
| 444 | td->maxcontacts = field->value[0]; | 417 | td->maxcontacts = field->value[0]; |
| 445 | if (!td->maxcontacts && | 418 | if (!td->maxcontacts && |
| 446 | field->logical_maximum <= MT_MAX_MAXCONTACT) | 419 | field->logical_maximum <= MT_MAX_MAXCONTACT) |
| @@ -1181,61 +1154,81 @@ static void mt_report(struct hid_device *hid, struct hid_report *report) | |||
| 1181 | input_sync(field->hidinput->input); | 1154 | input_sync(field->hidinput->input); |
| 1182 | } | 1155 | } |
| 1183 | 1156 | ||
| 1184 | static void mt_set_input_mode(struct hid_device *hdev) | 1157 | static bool mt_need_to_apply_feature(struct hid_device *hdev, |
| 1158 | struct hid_field *field, | ||
| 1159 | struct hid_usage *usage) | ||
| 1185 | { | 1160 | { |
| 1186 | struct mt_device *td = hid_get_drvdata(hdev); | 1161 | struct mt_device *td = hid_get_drvdata(hdev); |
| 1187 | struct hid_report *r; | ||
| 1188 | struct hid_report_enum *re; | ||
| 1189 | struct mt_class *cls = &td->mtclass; | 1162 | struct mt_class *cls = &td->mtclass; |
| 1163 | struct hid_report *report = field->report; | ||
| 1164 | unsigned int index = usage->usage_index; | ||
| 1190 | char *buf; | 1165 | char *buf; |
| 1191 | u32 report_len; | 1166 | u32 report_len; |
| 1167 | int max; | ||
| 1192 | 1168 | ||
| 1193 | if (td->inputmode < 0) | 1169 | switch (usage->hid) { |
| 1194 | return; | 1170 | case HID_DG_INPUTMODE: |
| 1195 | |||
| 1196 | re = &(hdev->report_enum[HID_FEATURE_REPORT]); | ||
| 1197 | r = re->report_id_hash[td->inputmode]; | ||
| 1198 | if (r) { | ||
| 1199 | if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) { | 1171 | if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) { |
| 1200 | report_len = hid_report_len(r); | 1172 | report_len = hid_report_len(report); |
| 1201 | buf = hid_alloc_report_buf(r, GFP_KERNEL); | 1173 | buf = hid_alloc_report_buf(report, GFP_KERNEL); |
| 1202 | if (!buf) { | 1174 | if (!buf) { |
| 1203 | hid_err(hdev, "failed to allocate buffer for report\n"); | 1175 | hid_err(hdev, |
| 1204 | return; | 1176 | "failed to allocate buffer for report\n"); |
| 1177 | return false; | ||
| 1205 | } | 1178 | } |
| 1206 | hid_hw_raw_request(hdev, r->id, buf, report_len, | 1179 | hid_hw_raw_request(hdev, report->id, buf, report_len, |
| 1207 | HID_FEATURE_REPORT, | 1180 | HID_FEATURE_REPORT, |
| 1208 | HID_REQ_GET_REPORT); | 1181 | HID_REQ_GET_REPORT); |
| 1209 | kfree(buf); | 1182 | kfree(buf); |
| 1210 | } | 1183 | } |
| 1211 | r->field[0]->value[td->inputmode_index] = td->inputmode_value; | ||
| 1212 | hid_hw_request(hdev, r, HID_REQ_SET_REPORT); | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | 1184 | ||
| 1216 | static void mt_set_maxcontacts(struct hid_device *hdev) | 1185 | field->value[index] = td->inputmode_value; |
| 1217 | { | 1186 | return true; |
| 1218 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 1219 | struct hid_report *r; | ||
| 1220 | struct hid_report_enum *re; | ||
| 1221 | int fieldmax, max; | ||
| 1222 | 1187 | ||
| 1223 | if (td->maxcontact_report_id < 0) | 1188 | case HID_DG_CONTACTMAX: |
| 1224 | return; | 1189 | if (td->mtclass.maxcontacts) { |
| 1190 | max = min_t(int, field->logical_maximum, | ||
| 1191 | td->mtclass.maxcontacts); | ||
| 1192 | if (field->value[index] != max) { | ||
| 1193 | field->value[index] = max; | ||
| 1194 | return true; | ||
| 1195 | } | ||
| 1196 | } | ||
| 1197 | break; | ||
| 1198 | } | ||
| 1225 | 1199 | ||
| 1226 | if (!td->mtclass.maxcontacts) | 1200 | return false; /* no need to update the report */ |
| 1227 | return; | 1201 | } |
| 1228 | 1202 | ||
| 1229 | re = &hdev->report_enum[HID_FEATURE_REPORT]; | 1203 | static void mt_set_modes(struct hid_device *hdev) |
| 1230 | r = re->report_id_hash[td->maxcontact_report_id]; | 1204 | { |
| 1231 | if (r) { | 1205 | struct hid_report_enum *rep_enum; |
| 1232 | max = td->mtclass.maxcontacts; | 1206 | struct hid_report *rep; |
| 1233 | fieldmax = r->field[0]->logical_maximum; | 1207 | struct hid_usage *usage; |
| 1234 | max = min(fieldmax, max); | 1208 | int i, j; |
| 1235 | if (r->field[0]->value[0] != max) { | 1209 | bool update_report; |
| 1236 | r->field[0]->value[0] = max; | 1210 | |
| 1237 | hid_hw_request(hdev, r, HID_REQ_SET_REPORT); | 1211 | rep_enum = &hdev->report_enum[HID_FEATURE_REPORT]; |
| 1212 | list_for_each_entry(rep, &rep_enum->report_list, list) { | ||
| 1213 | update_report = false; | ||
| 1214 | |||
| 1215 | for (i = 0; i < rep->maxfield; i++) { | ||
| 1216 | /* Ignore if report count is out of bounds. */ | ||
| 1217 | if (rep->field[i]->report_count < 1) | ||
| 1218 | continue; | ||
| 1219 | |||
| 1220 | for (j = 0; j < rep->field[i]->maxusage; j++) { | ||
| 1221 | usage = &rep->field[i]->usage[j]; | ||
| 1222 | |||
| 1223 | if (mt_need_to_apply_feature(hdev, | ||
| 1224 | rep->field[i], | ||
| 1225 | usage)) | ||
| 1226 | update_report = true; | ||
| 1227 | } | ||
| 1238 | } | 1228 | } |
| 1229 | |||
| 1230 | if (update_report) | ||
| 1231 | hid_hw_request(hdev, rep, HID_REQ_SET_REPORT); | ||
| 1239 | } | 1232 | } |
| 1240 | } | 1233 | } |
| 1241 | 1234 | ||
| @@ -1428,8 +1421,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1428 | } | 1421 | } |
| 1429 | td->hdev = hdev; | 1422 | td->hdev = hdev; |
| 1430 | td->mtclass = *mtclass; | 1423 | td->mtclass = *mtclass; |
| 1431 | td->inputmode = -1; | ||
| 1432 | td->maxcontact_report_id = -1; | ||
| 1433 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; | 1424 | td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; |
| 1434 | td->cc_index = -1; | 1425 | td->cc_index = -1; |
| 1435 | td->scantime_index = -1; | 1426 | td->scantime_index = -1; |
| @@ -1476,8 +1467,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1476 | dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", | 1467 | dev_warn(&hdev->dev, "Cannot allocate sysfs group for %s\n", |
| 1477 | hdev->name); | 1468 | hdev->name); |
| 1478 | 1469 | ||
| 1479 | mt_set_maxcontacts(hdev); | 1470 | mt_set_modes(hdev); |
| 1480 | mt_set_input_mode(hdev); | ||
| 1481 | 1471 | ||
| 1482 | /* release .fields memory as it is not used anymore */ | 1472 | /* release .fields memory as it is not used anymore */ |
| 1483 | devm_kfree(&hdev->dev, td->fields); | 1473 | devm_kfree(&hdev->dev, td->fields); |
| @@ -1490,8 +1480,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1490 | static int mt_reset_resume(struct hid_device *hdev) | 1480 | static int mt_reset_resume(struct hid_device *hdev) |
| 1491 | { | 1481 | { |
| 1492 | mt_release_contacts(hdev); | 1482 | mt_release_contacts(hdev); |
| 1493 | mt_set_maxcontacts(hdev); | 1483 | mt_set_modes(hdev); |
| 1494 | mt_set_input_mode(hdev); | ||
| 1495 | return 0; | 1484 | return 0; |
| 1496 | } | 1485 | } |
| 1497 | 1486 | ||
