Skip to content

Commit 5b65c2a

Browse files
bentissJiri Kosina
authored andcommitted
HID: rmi: check sanity of the incoming report
In the Dell XPS 13 9333, it appears that sometimes the bus get confused and corrupts the incoming data. It fills the input report with the sentinel value "ff". Synaptics told us that such behavior does not comes from the touchpad itself, so we filter out such reports here. Unfortunately, we can not simply discard the incoming data because they may contain useful information. Most of the time, the misbehavior is quite near the end of the report, so we can still use the valid part of it. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1123584 Signed-off-by: Benjamin Tissoires <[email protected]> Signed-off-by: Andrew Duggan <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent ff0c57a commit 5b65c2a

File tree

1 file changed

+38
-6
lines changed

1 file changed

+38
-6
lines changed

drivers/hid/hid-rmi.c

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -320,10 +320,7 @@ static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data,
320320
int offset;
321321
int i;
322322

323-
if (size < hdata->f11.report_size)
324-
return 0;
325-
326-
if (!(irq & hdata->f11.irq_mask))
323+
if (!(irq & hdata->f11.irq_mask) || size <= 0)
327324
return 0;
328325

329326
offset = (hdata->max_fingers >> 2) + 1;
@@ -332,9 +329,19 @@ static int rmi_f11_input_event(struct hid_device *hdev, u8 irq, u8 *data,
332329
int fs_bit_position = (i & 0x3) << 1;
333330
int finger_state = (data[fs_byte_position] >> fs_bit_position) &
334331
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+
}
335343

336-
rmi_f11_process_touch(hdata, i, finger_state,
337-
&data[offset + 5 * i]);
344+
rmi_f11_process_touch(hdata, i, finger_state, &data[position]);
338345
}
339346
input_mt_sync_frame(hdata->input);
340347
input_sync(hdata->input);
@@ -352,6 +359,11 @@ static int rmi_f30_input_event(struct hid_device *hdev, u8 irq, u8 *data,
352359
if (!(irq & hdata->f30.irq_mask))
353360
return 0;
354361

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+
355367
for (i = 0; i < hdata->gpio_led_count; i++) {
356368
if (test_bit(i, &hdata->button_mask)) {
357369
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)
412424
return 1;
413425
}
414426

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+
415443
static int rmi_raw_event(struct hid_device *hdev,
416444
struct hid_report *report, u8 *data, int size)
417445
{
446+
size = rmi_check_sanity(hdev, data, size);
447+
if (size < 2)
448+
return 0;
449+
418450
switch (data[0]) {
419451
case RMI_READ_DATA_REPORT_ID:
420452
return rmi_read_data_event(hdev, data, size);

0 commit comments

Comments
 (0)