diff options
| -rw-r--r-- | drivers/hid/hid-rmi.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 8389e8109218..3cccff73b9b9 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c | |||
| @@ -320,10 +320,7 @@ static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data, | |||
| 320 | int offset; | 320 | int offset; |
| 321 | int i; | 321 | int i; |
| 322 | 322 | ||
| 323 | if (size < hdata->f11.report_size) | 323 | if (!(irq & hdata->f11.irq_mask) || size <= 0) |
| 324 | return 0; | ||
| 325 | |||
| 326 | if (!(irq & hdata->f11.irq_mask)) | ||
| 327 | return 0; | 324 | return 0; |
| 328 | 325 | ||
| 329 | offset = (hdata->max_fingers >> 2) + 1; | 326 | offset = (hdata->max_fingers >> 2) + 1; |
| @@ -332,9 +329,19 @@ static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data, | |||
| 332 | int fs_bit_position = (i & 0x3) << 1; | 329 | int fs_bit_position = (i & 0x3) << 1; |
| 333 | int finger_state = (data[fs_byte_position] >> fs_bit_position) & | 330 | int finger_state = (data[fs_byte_position] >> fs_bit_position) & |
| 334 | 0x03; | 331 | 0x03; |
| 332 | int position = offset + 5 * i; | ||
| 333 | |||
| 334 | if (position + 5 > size) { | ||
| 335 | /* partial report, go on with what we received */ | ||
| 336 | printk_once(KERN_WARNING | ||
| 337 | "%s %s: Detected incomplete finger report. Finger reports may occasionally get dropped on this platform.\n", | ||
| 338 | dev_driver_string(&hdev->dev), | ||
| 339 | dev_name(&hdev->dev)); | ||
| 340 | hid_dbg(hdev, "Incomplete finger report\n"); | ||
| 341 | break; | ||
| 342 | } | ||
| 335 | 343 | ||
| 336 | rmi_f11_process_touch(hdata, i, finger_state, | 344 | rmi_f11_process_touch(hdata, i, finger_state, &data[position]); |
| 337 | &data[offset + 5 * i]); | ||
| 338 | } | 345 | } |
| 339 | input_mt_sync_frame(hdata->input); | 346 | input_mt_sync_frame(hdata->input); |
| 340 | input_sync(hdata->input); | 347 | input_sync(hdata->input); |
| @@ -352,6 +359,11 @@ static int rmi_f30_input_event(struct hid_device *hdev, u8 irq, u8 *data, | |||
| 352 | if (!(irq & hdata->f30.irq_mask)) | 359 | if (!(irq & hdata->f30.irq_mask)) |
| 353 | return 0; | 360 | return 0; |
| 354 | 361 | ||
| 362 | if (size < (int)hdata->f30.report_size) { | ||
| 363 | hid_warn(hdev, "Click Button pressed, but the click data is missing\n"); | ||
| 364 | return 0; | ||
| 365 | } | ||
| 366 | |||
| 355 | for (i = 0; i < hdata->gpio_led_count; i++) { | 367 | for (i = 0; i < hdata->gpio_led_count; i++) { |
| 356 | if (test_bit(i, &hdata->button_mask)) { | 368 | if (test_bit(i, &hdata->button_mask)) { |
| 357 | value = (data[i / 8] >> (i & 0x07)) & BIT(0); | 369 | value = (data[i / 8] >> (i & 0x07)) & BIT(0); |
| @@ -412,9 +424,29 @@ static int rmi_read_data_event(struct hid_device *hdev, u8 *data, int size) | |||
| 412 | return 1; | 424 | return 1; |
| 413 | } | 425 | } |
| 414 | 426 | ||
| 427 | static int rmi_check_sanity(struct hid_device *hdev, u8 *data, int size) | ||
| 428 | { | ||
| 429 | int valid_size = size; | ||
| 430 | /* | ||
| 431 | * On the Dell XPS 13 9333, the bus sometimes get confused and fills | ||
| 432 | * the report with a sentinel value "ff". Synaptics told us that such | ||
| 433 | * behavior does not comes from the touchpad itself, so we filter out | ||
| 434 | * such reports here. | ||
| 435 | */ | ||
| 436 | |||
| 437 | while ((data[valid_size - 1] == 0xff) && valid_size > 0) | ||
| 438 | valid_size--; | ||
| 439 | |||
| 440 | return valid_size; | ||
| 441 | } | ||
| 442 | |||
| 415 | static int rmi_raw_event(struct hid_device *hdev, | 443 | static int rmi_raw_event(struct hid_device *hdev, |
| 416 | struct hid_report *report, u8 *data, int size) | 444 | struct hid_report *report, u8 *data, int size) |
| 417 | { | 445 | { |
| 446 | size = rmi_check_sanity(hdev, data, size); | ||
| 447 | if (size < 2) | ||
| 448 | return 0; | ||
| 449 | |||
| 418 | switch (data[0]) { | 450 | switch (data[0]) { |
| 419 | case RMI_READ_DATA_REPORT_ID: | 451 | case RMI_READ_DATA_REPORT_ID: |
| 420 | return rmi_read_data_event(hdev, data, size); | 452 | return rmi_read_data_event(hdev, data, size); |
