aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/hid-multitouch.c131
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
1184static void mt_set_input_mode(struct hid_device *hdev) 1157static 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
1216static 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]; 1203static 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)
1490static int mt_reset_resume(struct hid_device *hdev) 1480static 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