[media] ati_remote: switch to single-byte scancodes

The ati_remote driver currently uses 2-byte scancodes. However, one of
those bytes is actually a checksum and therefore shouldn't be considered
as part of the scancode.

Fix the driver to only use the actual data byte as a scancode and to
check the checksum itself. Update the bundled keymaps accordingly.

Since ati_remote was only migrated to the rc subsystem for 3.2, the
previous scancodes weren't emitted on any stable kernel.

Reported-by: George Spelvin <linux@horizon.com>
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
index 303f22e..01bb8da 100644
--- a/drivers/media/rc/ati_remote.c
+++ b/drivers/media/rc/ati_remote.c
@@ -189,7 +189,7 @@
 	dma_addr_t inbuf_dma;
 	dma_addr_t outbuf_dma;
 
-	unsigned char old_data[2];  /* Detect duplicate events */
+	unsigned char old_data;     /* Detect duplicate events */
 	unsigned long old_jiffies;
 	unsigned long acc_jiffies;  /* handle acceleration */
 	unsigned long first_jiffies;
@@ -221,35 +221,35 @@
 /* Translation table from hardware messages to input events. */
 static const struct {
 	short kind;
-	unsigned char data1, data2;
+	unsigned char data;
 	int type;
 	unsigned int code;
 	int value;
 }  ati_remote_tbl[] = {
 	/* Directional control pad axes */
-	{KIND_ACCEL,   0x35, 0x70, EV_REL, REL_X, -1},	 /* left */
-	{KIND_ACCEL,   0x36, 0x71, EV_REL, REL_X, 1},    /* right */
-	{KIND_ACCEL,   0x37, 0x72, EV_REL, REL_Y, -1},	 /* up */
-	{KIND_ACCEL,   0x38, 0x73, EV_REL, REL_Y, 1},    /* down */
+	{KIND_ACCEL,   0x70, EV_REL, REL_X, -1},   /* left */
+	{KIND_ACCEL,   0x71, EV_REL, REL_X, 1},    /* right */
+	{KIND_ACCEL,   0x72, EV_REL, REL_Y, -1},   /* up */
+	{KIND_ACCEL,   0x73, EV_REL, REL_Y, 1},    /* down */
 	/* Directional control pad diagonals */
-	{KIND_LU,      0x39, 0x74, EV_REL, 0, 0},        /* left up */
-	{KIND_RU,      0x3a, 0x75, EV_REL, 0, 0},        /* right up */
-	{KIND_LD,      0x3c, 0x77, EV_REL, 0, 0},        /* left down */
-	{KIND_RD,      0x3b, 0x76, EV_REL, 0, 0},        /* right down */
+	{KIND_LU,      0x74, EV_REL, 0, 0},        /* left up */
+	{KIND_RU,      0x75, EV_REL, 0, 0},        /* right up */
+	{KIND_LD,      0x77, EV_REL, 0, 0},        /* left down */
+	{KIND_RD,      0x76, EV_REL, 0, 0},        /* right down */
 
 	/* "Mouse button" buttons */
-	{KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
-	{KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
-	{KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
-	{KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
+	{KIND_LITERAL, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */
+	{KIND_LITERAL, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */
+	{KIND_LITERAL, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */
+	{KIND_LITERAL, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */
 
 	/* Artificial "doubleclick" events are generated by the hardware.
 	 * They are mapped to the "side" and "extra" mouse buttons here. */
-	{KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
-	{KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
+	{KIND_FILTERED, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */
+	{KIND_FILTERED, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */
 
 	/* Non-mouse events are handled by rc-core */
-	{KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0}
+	{KIND_END, 0x00, EV_MAX + 1, 0, 0}
 };
 
 /* Local function prototypes */
@@ -397,25 +397,6 @@
 }
 
 /*
- *	ati_remote_event_lookup
- */
-static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2)
-{
-	int i;
-
-	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
-		/*
-		 * Decide if the table entry matches the remote input.
-		 */
-		if (ati_remote_tbl[i].data1 == d1 &&
-		    ati_remote_tbl[i].data2 == d2)
-			return i;
-
-	}
-	return -1;
-}
-
-/*
  *	ati_remote_compute_accel
  *
  * Implements acceleration curve for directional control pad
@@ -463,7 +444,15 @@
 	int index = -1;
 	int acc;
 	int remote_num;
-	unsigned char scancode[2];
+	unsigned char scancode;
+	int i;
+
+	/*
+	 * data[0] = 0x14
+	 * data[1] = data[2] + data[3] + 0xd5 (a checksum byte)
+	 * data[2] = the key code (with toggle bit in MSB with some models)
+	 * data[3] = channel << 4 (the low 4 bits must be zero)
+	 */
 
 	/* Deal with strange looking inputs */
 	if ( (urb->actual_length != 4) || (data[0] != 0x14) ||
@@ -472,6 +461,13 @@
 		return;
 	}
 
+	if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
+		dbginfo(&ati_remote->interface->dev,
+			"wrong checksum in input: %02x %02x %02x %02x\n",
+			data[0], data[1], data[2], data[3]);
+		return;
+	}
+
 	/* Mask unwanted remote channels.  */
 	/* note: remote_num is 0-based, channel 1 on remote == 0 here */
 	remote_num = (data[3] >> 4) & 0x0f;
@@ -482,31 +478,30 @@
 		return;
 	}
 
-	scancode[0] = (((data[1] - ((remote_num + 1) << 4)) & 0xf0) | (data[1] & 0x0f));
-
 	/*
-	 * Some devices (e.g. SnapStream Firefly) use 8080 as toggle code,
-	 * so we have to clear them. The first bit is a bit tricky as the
-	 * "non-toggled" state depends on remote_num, so we xor it with the
-	 * second bit which is only used for toggle.
+	 * MSB is a toggle code, though only used by some devices
+	 * (e.g. SnapStream Firefly)
 	 */
-	scancode[0] ^= (data[2] & 0x80);
+	scancode = data[2] & 0x7f;
 
-	scancode[1] = data[2] & ~0x80;
-
-	/* Look up event code index in mouse translation table. */
-	index = ati_remote_event_lookup(remote_num, scancode[0], scancode[1]);
+	/* Look up event code index in the mouse translation table. */
+	for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
+		if (scancode == ati_remote_tbl[i].data) {
+			index = i;
+			break;
+		}
+	}
 
 	if (index >= 0) {
 		dbginfo(&ati_remote->interface->dev,
-			"channel 0x%02x; mouse data %02x,%02x; index %d; keycode %d\n",
-			remote_num, data[1], data[2], index, ati_remote_tbl[index].code);
+			"channel 0x%02x; mouse data %02x; index %d; keycode %d\n",
+			remote_num, data[2], index, ati_remote_tbl[index].code);
 		if (!dev)
 			return; /* no mouse device */
 	} else
 		dbginfo(&ati_remote->interface->dev,
-			"channel 0x%02x; key data %02x,%02x, scancode %02x,%02x\n",
-			remote_num, data[1], data[2], scancode[0], scancode[1]);
+			"channel 0x%02x; key data %02x, scancode %02x\n",
+			remote_num, data[2], scancode);
 
 
 	if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
@@ -523,8 +518,7 @@
 		unsigned long now = jiffies;
 
 		/* Filter duplicate events which happen "too close" together. */
-		if (ati_remote->old_data[0] == data[1] &&
-		    ati_remote->old_data[1] == data[2] &&
+		if (ati_remote->old_data == data[2] &&
 		    time_before(now, ati_remote->old_jiffies +
 				     msecs_to_jiffies(repeat_filter))) {
 			ati_remote->repeat_count++;
@@ -533,8 +527,7 @@
 			ati_remote->first_jiffies = now;
 		}
 
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
+		ati_remote->old_data = data[2];
 		ati_remote->old_jiffies = now;
 
 		/* Ensure we skip at least the 4 first duplicate events (generated
@@ -549,14 +542,13 @@
 
 		if (index < 0) {
 			/* Not a mouse event, hand it to rc-core. */
-			u32 rc_code = (scancode[0] << 8) | scancode[1];
 
 			/*
 			 * We don't use the rc-core repeat handling yet as
 			 * it would cause ghost repeats which would be a
 			 * regression for this driver.
 			 */
-			rc_keydown_notimeout(ati_remote->rdev, rc_code,
+			rc_keydown_notimeout(ati_remote->rdev, scancode,
 					     data[2]);
 			rc_keyup(ati_remote->rdev);
 			return;
@@ -607,8 +599,7 @@
 		input_sync(dev);
 
 		ati_remote->old_jiffies = jiffies;
-		ati_remote->old_data[0] = data[1];
-		ati_remote->old_data[1] = data[2];
+		ati_remote->old_data = data[2];
 	}
 }