diff options
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 661b4fce1a5d..dd64461e5e85 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -309,6 +309,41 @@ static struct attribute_group mt_attribute_group = { | |||
| 309 | .attrs = sysfs_attrs | 309 | .attrs = sysfs_attrs |
| 310 | }; | 310 | }; |
| 311 | 311 | ||
| 312 | static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) | ||
| 313 | { | ||
| 314 | struct mt_device *td = hid_get_drvdata(hdev); | ||
| 315 | int ret, size = hid_report_len(report); | ||
| 316 | u8 *buf; | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Only fetch the feature report if initial reports are not already | ||
| 320 | * been retrieved. Currently this is only done for Windows 8 touch | ||
| 321 | * devices. | ||
| 322 | */ | ||
| 323 | if (!(hdev->quirks & HID_QUIRK_NO_INIT_REPORTS)) | ||
| 324 | return; | ||
| 325 | if (td->mtclass.name != MT_CLS_WIN_8) | ||
| 326 | return; | ||
| 327 | |||
| 328 | buf = hid_alloc_report_buf(report, GFP_KERNEL); | ||
| 329 | if (!buf) | ||
| 330 | return; | ||
| 331 | |||
| 332 | ret = hid_hw_raw_request(hdev, report->id, buf, size, | ||
| 333 | HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | ||
| 334 | if (ret < 0) { | ||
| 335 | dev_warn(&hdev->dev, "failed to fetch feature %d\n", | ||
| 336 | report->id); | ||
| 337 | } else { | ||
| 338 | ret = hid_report_raw_event(hdev, HID_FEATURE_REPORT, buf, | ||
| 339 | size, 0); | ||
| 340 | if (ret) | ||
| 341 | dev_warn(&hdev->dev, "failed to report feature\n"); | ||
| 342 | } | ||
| 343 | |||
| 344 | kfree(buf); | ||
| 345 | } | ||
| 346 | |||
| 312 | static void mt_feature_mapping(struct hid_device *hdev, | 347 | static void mt_feature_mapping(struct hid_device *hdev, |
| 313 | struct hid_field *field, struct hid_usage *usage) | 348 | struct hid_field *field, struct hid_usage *usage) |
| 314 | { | 349 | { |
| @@ -327,6 +362,8 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 327 | 362 | ||
| 328 | break; | 363 | break; |
| 329 | case HID_DG_CONTACTMAX: | 364 | case HID_DG_CONTACTMAX: |
| 365 | mt_get_feature(hdev, field->report); | ||
| 366 | |||
| 330 | td->maxcontact_report_id = field->report->id; | 367 | td->maxcontact_report_id = field->report->id; |
| 331 | td->maxcontacts = field->value[0]; | 368 | td->maxcontacts = field->value[0]; |
| 332 | if (!td->maxcontacts && | 369 | if (!td->maxcontacts && |
| @@ -343,6 +380,7 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 343 | break; | 380 | break; |
| 344 | } | 381 | } |
| 345 | 382 | ||
| 383 | mt_get_feature(hdev, field->report); | ||
| 346 | if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD) | 384 | if (field->value[usage->usage_index] == MT_BUTTONTYPE_CLICKPAD) |
| 347 | td->is_buttonpad = true; | 385 | td->is_buttonpad = true; |
| 348 | 386 | ||
| @@ -1029,8 +1067,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 1029 | * reports. Fortunately, the Win8 spec says that all touches | 1067 | * reports. Fortunately, the Win8 spec says that all touches |
| 1030 | * should be sent during each report, making the initialization | 1068 | * should be sent during each report, making the initialization |
| 1031 | * of input reports unnecessary. | 1069 | * of input reports unnecessary. |
| 1070 | * | ||
| 1071 | * In addition some touchpads do not behave well if we read | ||
| 1072 | * all feature reports from them. Instead we prevent | ||
| 1073 | * initial report fetching and then selectively fetch each | ||
| 1074 | * report we are interested in. | ||
| 1032 | */ | 1075 | */ |
| 1033 | hdev->quirks |= HID_QUIRK_NO_INIT_INPUT_REPORTS; | 1076 | hdev->quirks |= HID_QUIRK_NO_INIT_REPORTS; |
| 1034 | 1077 | ||
| 1035 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); | 1078 | td = devm_kzalloc(&hdev->dev, sizeof(struct mt_device), GFP_KERNEL); |
| 1036 | if (!td) { | 1079 | if (!td) { |
