aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2018-01-17 12:00:24 -0800
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2018-02-02 16:50:28 -0800
commit29acc42e8e10a4721757af9ed8aec569d30ce39b (patch)
treeec5af27e25a76eae0f376029f93755032f253711 /drivers
parentInput: libps2 - support retransmission of command data (diff)
downloadlinux-dev-29acc42e8e10a4721757af9ed8aec569d30ce39b.tar.xz
linux-dev-29acc42e8e10a4721757af9ed8aec569d30ce39b.zip
Input: libps2 - relax command byte ACK handling
When we probe PS/2 devices we first issue "Get ID" command and only if we receive what we consider a valid keyboard or mouse ID we disable the device and continue with protocol detection. That means that the device may be transmitting motion or keystroke data, while we expect ACK response. Instead of signaling failure if we see anything but ACK/NAK let's ignore "garbage" response until we see ACK for the command byte (first byte). The checks for subsequent ACKs of command parameters will continue be strict. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/serio/libps2.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index f05c407b31f3..e6a07e68d1ff 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -256,16 +256,23 @@ int __ps2_command(struct ps2dev *ps2dev, u8 *param, unsigned int command)
for (i = 0; i < receive; i++)
ps2dev->cmdbuf[(receive - 1) - i] = param[i];
+ /* Signal that we are sending the command byte */
+ ps2dev->flags |= PS2_FLAG_ACK_CMD;
+
/*
* Some devices (Synaptics) peform the reset before
* ACKing the reset command, and so it can take a long
* time before the ACK arrives.
*/
- rc = ps2_do_sendbyte(ps2dev, command & 0xff,
- command == PS2_CMD_RESET_BAT ? 1000 : 200, 2);
+ timeout = command == PS2_CMD_RESET_BAT ? 1000 : 200;
+
+ rc = ps2_do_sendbyte(ps2dev, command & 0xff, timeout, 2);
if (rc)
goto out_reset_flags;
+ /* Now we are sending command parameters, if any */
+ ps2dev->flags &= ~PS2_FLAG_ACK_CMD;
+
for (i = 0; i < send; i++) {
rc = ps2_do_sendbyte(ps2dev, param[i], 200, 2);
if (rc)
@@ -416,7 +423,19 @@ bool ps2_handle_ack(struct ps2dev *ps2dev, u8 data)
}
/* Fall through */
default:
- return false;
+ /*
+ * Do not signal errors if we get unexpected reply while
+ * waiting for an ACK to the initial (first) command byte:
+ * the device might not be quiesced yet and continue
+ * delivering data.
+ * Note that we reset PS2_FLAG_WAITID flag, so the workaround
+ * for mice not acknowledging the Get ID command only triggers
+ * on the 1st byte; if device spews data we really want to see
+ * a real ACK from it.
+ */
+ dev_dbg(&ps2dev->serio->dev, "unexpected %#02x\n", data);
+ ps2dev->flags &= ~PS2_FLAG_WAITID;
+ return ps2dev->flags & PS2_FLAG_ACK_CMD;
}
if (!ps2dev->nak) {