From 9807879bfdc0c2b5106b4b378f5475c6a333d853 Mon Sep 17 00:00:00 2001
From: Dmitry Torokhov <dtor@insightbb.com>
Date: Thu, 14 Sep 2006 01:31:27 -0400
Subject: Input: atkbd - support Microsoft Natural Elite Pro keyboards

Microsoft Natural Elite Pro keyboard produces unisual response to
the GET ID command - single byte 0xaa (normally keyboards produce
2-byte response). Fail GET ID command so atkbd gets a change to
do alternate probe.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
---
 drivers/input/keyboard/atkbd.c |  4 +---
 drivers/input/serio/libps2.c   | 18 ++++++++++++++++--
 include/linux/libps2.h         |  1 +
 3 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ce1f10e898..9874072cf9 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -635,9 +635,7 @@ static int atkbd_probe(struct atkbd *atkbd)
 		return 0;
 	}
 
-	if (param[0] != 0xab && param[0] != 0xac &&	/* Regular and NCD Sun keyboards */
-	    param[0] != 0x2b && param[0] != 0x5d &&	/* Trust keyboard, raw and translated */
-	    param[0] != 0x60 && param[0] != 0x47)	/* NMB SGI keyboard, raw and translated */
+	if (!ps2_is_keyboard_id(param[0]))
 		return -1;
 
 	atkbd->id = (param[0] << 8) | param[1];
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c
index ed202f2f25..e0a2297a9d 100644
--- a/drivers/input/serio/libps2.c
+++ b/drivers/input/serio/libps2.c
@@ -35,6 +35,7 @@ EXPORT_SYMBOL(ps2_schedule_command);
 EXPORT_SYMBOL(ps2_handle_ack);
 EXPORT_SYMBOL(ps2_handle_response);
 EXPORT_SYMBOL(ps2_cmd_aborted);
+EXPORT_SYMBOL(ps2_is_keyboard_id);
 
 /* Work structure to schedule execution of a command */
 struct ps2work {
@@ -102,9 +103,9 @@ void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout)
  * known keyboard IDs.
  */
 
-static inline int ps2_is_keyboard_id(char id_byte)
+int ps2_is_keyboard_id(char id_byte)
 {
-	static char keyboard_ids[] = {
+	const static char keyboard_ids[] = {
 		0xab,	/* Regular keyboards		*/
 		0xac,	/* NCD Sun keyboard		*/
 		0x2b,	/* Trust keyboard, translated	*/
@@ -138,6 +139,19 @@ static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout)
 			break;
 
 		case PS2_CMD_GETID:
+			/*
+			 * Microsoft Natural Elite keyboard responds to
+			 * the GET ID command as it were a mouse, with
+			 * a single byte. Fail the command so atkbd will
+			 * use alternative probe to detect it.
+			 */
+			if (ps2dev->cmdbuf[1] == 0xaa) {
+				serio_pause_rx(ps2dev->serio);
+				ps2dev->flags = 0;
+				serio_continue_rx(ps2dev->serio);
+				timeout = 0;
+			}
+
 			/*
 			 * If device behind the port is not a keyboard there
 			 * won't be 2nd byte of ID response.
diff --git a/include/linux/libps2.h b/include/linux/libps2.h
index 08a450a9db..f6f301e2b0 100644
--- a/include/linux/libps2.h
+++ b/include/linux/libps2.h
@@ -47,5 +47,6 @@ int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int comman
 int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data);
 int ps2_handle_response(struct ps2dev *ps2dev, unsigned char data);
 void ps2_cmd_aborted(struct ps2dev *ps2dev);
+int ps2_is_keyboard_id(char id);
 
 #endif /* _LIBPS2_H */
-- 
cgit v1.2.2