diff options
author | Andrew Duggan <aduggan@synaptics.com> | 2016-11-09 03:46:20 +0300 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2016-11-09 04:12:06 +0300 |
commit | 6d0dbeae71f074c67b081eae45cd58fa39dfda2e (patch) | |
tree | 4ab16cc8a6cc37d0e9584dfe5ba764a88dabd1f8 /drivers/input/rmi4/rmi_f11.c | |
parent | 3aeed5b573f97b4525841cc07c1e948227af389f (diff) | |
download | linux-6d0dbeae71f074c67b081eae45cd58fa39dfda2e.tar.xz |
Input: synaptics-rmi4 - handle incomplete input data
Commit 5b65c2a02966 ("HID: rmi: check sanity of the incoming report") added
support for handling incomplete HID reports do to the input data being
corrupted in transit. This patch reimplements this functionality in the
function drivers so they can handle getting less valid data then they
expect.
Signed-off-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input/rmi4/rmi_f11.c')
-rw-r--r-- | drivers/input/rmi4/rmi_f11.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c index 20c7134b3d3b..3218742d2d8c 100644 --- a/drivers/input/rmi4/rmi_f11.c +++ b/drivers/input/rmi4/rmi_f11.c @@ -572,31 +572,48 @@ static inline u8 rmi_f11_parse_finger_state(const u8 *f_state, u8 n_finger) static void rmi_f11_finger_handler(struct f11_data *f11, struct rmi_2d_sensor *sensor, - unsigned long *irq_bits, int num_irq_regs) + unsigned long *irq_bits, int num_irq_regs, + int size) { const u8 *f_state = f11->data.f_state; u8 finger_state; u8 i; + int abs_fingers; + int rel_fingers; + int abs_size = sensor->nbr_fingers * RMI_F11_ABS_BYTES; int abs_bits = bitmap_and(f11->result_bits, irq_bits, f11->abs_mask, num_irq_regs * 8); int rel_bits = bitmap_and(f11->result_bits, irq_bits, f11->rel_mask, num_irq_regs * 8); - for (i = 0; i < sensor->nbr_fingers; i++) { - /* Possible of having 4 fingers per f_statet register */ - finger_state = rmi_f11_parse_finger_state(f_state, i); - if (finger_state == F11_RESERVED) { - pr_err("Invalid finger state[%d]: 0x%02x", i, - finger_state); - continue; - } + if (abs_bits) { + if (abs_size > size) + abs_fingers = size / RMI_F11_ABS_BYTES; + else + abs_fingers = sensor->nbr_fingers; + + for (i = 0; i < abs_fingers; i++) { + /* Possible of having 4 fingers per f_state register */ + finger_state = rmi_f11_parse_finger_state(f_state, i); + if (finger_state == F11_RESERVED) { + pr_err("Invalid finger state[%d]: 0x%02x", i, + finger_state); + continue; + } - if (abs_bits) rmi_f11_abs_pos_process(f11, sensor, &sensor->objs[i], finger_state, i); + } + } + + if (rel_bits) { + if ((abs_size + sensor->nbr_fingers * RMI_F11_REL_BYTES) > size) + rel_fingers = (size - abs_size) / RMI_F11_REL_BYTES; + else + rel_fingers = sensor->nbr_fingers; - if (rel_bits) + for (i = 0; i < rel_fingers; i++) rmi_f11_rel_pos_report(f11, i); } @@ -612,7 +629,7 @@ static void rmi_f11_finger_handler(struct f11_data *f11, sensor->nbr_fingers, sensor->dmax); - for (i = 0; i < sensor->nbr_fingers; i++) { + for (i = 0; i < abs_fingers; i++) { finger_state = rmi_f11_parse_finger_state(f_state, i); if (finger_state == F11_RESERVED) /* no need to send twice the error */ @@ -1242,10 +1259,19 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits) struct f11_data *f11 = dev_get_drvdata(&fn->dev); u16 data_base_addr = fn->fd.data_base_addr; int error; + int valid_bytes = f11->sensor.pkt_size; if (rmi_dev->xport->attn_data) { + /* + * The valid data in the attention report is less then + * expected. Only process the complete fingers. + */ + if (f11->sensor.attn_size > rmi_dev->xport->attn_size) + valid_bytes = rmi_dev->xport->attn_size; + else + valid_bytes = f11->sensor.attn_size; memcpy(f11->sensor.data_pkt, rmi_dev->xport->attn_data, - f11->sensor.attn_size); + valid_bytes); rmi_dev->xport->attn_data += f11->sensor.attn_size; rmi_dev->xport->attn_size -= f11->sensor.attn_size; } else { @@ -1257,7 +1283,7 @@ static int rmi_f11_attention(struct rmi_function *fn, unsigned long *irq_bits) } rmi_f11_finger_handler(f11, &f11->sensor, irq_bits, - drvdata->num_of_irq_regs); + drvdata->num_of_irq_regs, valid_bytes); return 0; } |