Skip to content

Commit

Permalink
Input: synaptics-rmi4 - f03 - grab data passed by transport device
Browse files Browse the repository at this point in the history
First check if there are data available passed by the transport device.
If data available use these data. If there are no data available
try to read the rmi block if dsata are passed this way.

This is the way the other rmi function handlers will do this.

This patch is needed on HID devices because the firmware reads F03 data
registers and adds them to the HID attention report. Reading those
registers from the driver after the firmware read them will result in
invalid data.

Reviewed-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Dennis Wassenberg <dennis.wassenberg@secunet.com>
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
  • Loading branch information
Dennis Wassenberg authored and Dmitry Torokhov committed Dec 3, 2016
1 parent c5e8848 commit e621132
Showing 1 changed file with 26 additions and 9 deletions.
35 changes: 26 additions & 9 deletions drivers/input/rmi4/rmi_f03.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ static int rmi_f03_config(struct rmi_function *fn)

static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
{
struct rmi_device *rmi_dev = fn->rmi_dev;
struct f03_data *f03 = dev_get_drvdata(&fn->dev);
u16 data_addr = fn->fd.data_base_addr;
const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
Expand All @@ -173,15 +174,31 @@ static int rmi_f03_attention(struct rmi_function *fn, unsigned long *irq_bits)
int i;
int error;

/* Grab all of the data registers, and check them for data */
error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
&obs, ob_len);
if (error) {
dev_err(&fn->dev,
"%s: Failed to read F03 output buffers: %d\n",
__func__, error);
serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
return error;
if (!rmi_dev || !rmi_dev->xport)
return -ENODEV;

if (rmi_dev->xport->attn_data) {
/* First grab the data passed by the transport device */
if (rmi_dev->xport->attn_size < ob_len) {
dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
return 0;
}

memcpy(obs, rmi_dev->xport->attn_data, ob_len);

rmi_dev->xport->attn_data += ob_len;
rmi_dev->xport->attn_size -= ob_len;
} else {
/* Grab all of the data registers, and check them for data */
error = rmi_read_block(fn->rmi_dev, data_addr + RMI_F03_OB_OFFSET,
&obs, ob_len);
if (error) {
dev_err(&fn->dev,
"%s: Failed to read F03 output buffers: %d\n",
__func__, error);
serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
return error;
}
}

for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {
Expand Down

0 comments on commit e621132

Please sign in to comment.