From: Dmitry Torokhov <dtor_core@ameritech.net>

synaptics driver cleanup

- pack all button data in 2 bytes instead of 48

- adjust the way we extract button data

- query extended capabilities if SYN_EXT_CAP_REQUESTS >= 1 (was == 1)
  according to Synaptics' addendum to the interfacing guide

- do not announce or report BTN_BACK/BTN_FORWARD unless touchpad has
  SYN_CAP_FOUR_BUTTON in its capability flags


---

 25-akpm/drivers/input/mouse/synaptics.c |  137 +++++++++++++-------------------
 25-akpm/drivers/input/mouse/synaptics.h |   19 +---
 2 files changed, 65 insertions(+), 91 deletions(-)

diff -puN drivers/input/mouse/synaptics.c~new-set-of-input-patches-synaptics-cleanup drivers/input/mouse/synaptics.c
--- 25/drivers/input/mouse/synaptics.c~new-set-of-input-patches-synaptics-cleanup	2004-04-21 00:22:20.629899064 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.c	2004-04-21 00:22:20.635898152 -0700
@@ -118,17 +118,31 @@ static int synaptics_capability(struct p
 
 	if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap))
 		return -1;
-	priv->capabilities = (cap[0]<<16) | (cap[1]<<8) | cap[2];
+	priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2];
 	priv->ext_cap = 0;
 	if (!SYN_CAP_VALID(priv->capabilities))
 		return -1;
 
-	if (SYN_EXT_CAP_REQUESTS(priv->capabilities)) {
+	/*
+	 * Unless capExtended is set the rest of the flags should be ignored
+	 */
+	if (!SYN_CAP_EXTENDED(priv->capabilities))
+		priv->capabilities = 0;
+
+	if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) {
 		if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) {
 			printk(KERN_ERR "Synaptics claims to have extended capabilities,"
 			       " but I'm not able to read them.");
-		} else
-			priv->ext_cap = (cap[0]<<16) | (cap[1]<<8) | cap[2];
+		} else {
+			priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2];
+
+			/*
+			 * if nExtBtn is greater than 8 it should be considered
+			 * invalid and treated as 0
+			 */
+			if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 8)
+				priv->ext_cap &= 0xff0fff;
+		}
 	}
 	return 0;
 }
@@ -167,11 +181,10 @@ static void print_ident(struct synaptics
 
 	if (SYN_CAP_EXTENDED(priv->capabilities)) {
 		printk(KERN_INFO " Touchpad has extended capability bits\n");
-		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
-		    SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) <= 8)
+		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
 			printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
 			       (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
-		else if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
+		if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
 			printk(KERN_INFO " -> four buttons\n");
 		if (SYN_CAP_MULTIFINGER(priv->capabilities))
 			printk(KERN_INFO " -> multifinger detection\n");
@@ -312,6 +325,8 @@ static inline void set_abs_params(struct
 
 static void set_input_params(struct input_dev *dev, struct synaptics_data *priv)
 {
+	int i;
+
 	set_bit(EV_ABS, dev->evbit);
 	set_abs_params(dev, ABS_X, XMIN_NOMINAL, XMAX_NOMINAL, 0, 0);
 	set_abs_params(dev, ABS_Y, YMIN_NOMINAL, YMAX_NOMINAL, 0, 0);
@@ -326,32 +341,15 @@ static void set_input_params(struct inpu
 
 	set_bit(BTN_LEFT, dev->keybit);
 	set_bit(BTN_RIGHT, dev->keybit);
-	set_bit(BTN_FORWARD, dev->keybit);
-	set_bit(BTN_BACK, dev->keybit);
-	if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) {
-		switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
-		default:
-			/*
-			 * if nExtBtn is greater than 8 it should be considered
-			 * invalid and treated as 0
-			 */
-			break;
-		case 8:
-			set_bit(BTN_7, dev->keybit);
-			set_bit(BTN_6, dev->keybit);
-		case 6:
-			set_bit(BTN_5, dev->keybit);
-			set_bit(BTN_4, dev->keybit);
-		case 4:
-			set_bit(BTN_3, dev->keybit);
-			set_bit(BTN_2, dev->keybit);
-		case 2:
-			set_bit(BTN_1, dev->keybit);
-			set_bit(BTN_0, dev->keybit);
-			break;
-		}
+
+	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+		set_bit(BTN_FORWARD, dev->keybit);
+		set_bit(BTN_BACK, dev->keybit);
 	}
 
+	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+		set_bit(BTN_0 + i, dev->keybit);
+
 	clear_bit(EV_REL, dev->evbit);
 	clear_bit(REL_X, dev->relbit);
 	clear_bit(REL_Y, dev->relbit);
@@ -385,8 +383,8 @@ static int synaptics_reconnect(struct ps
 	if (old_priv.identity != priv->identity ||
 	    old_priv.model_id != priv->model_id ||
 	    old_priv.capabilities != priv->capabilities ||
-    	    old_priv.ext_cap != priv->ext_cap)
-    		return -1;
+	    old_priv.ext_cap != priv->ext_cap)
+		return -1;
 
 	if (synaptics_set_mode(psmouse, 0)) {
 		printk(KERN_ERR "Unable to initialize Synaptics hardware.\n");
@@ -432,8 +430,8 @@ int synaptics_init(struct psmouse *psmou
 
 	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
-	if (SYN_CAP_EXTENDED(priv->capabilities) && SYN_CAP_PASS_THROUGH(priv->capabilities))
-       		synaptics_pt_create(psmouse);
+	if (SYN_CAP_PASS_THROUGH(priv->capabilities))
+		synaptics_pt_create(psmouse);
 
 	print_ident(priv);
 	set_input_params(&psmouse->dev, priv);
@@ -471,17 +469,14 @@ static void synaptics_parse_hw_state(uns
 
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
-		if (SYN_CAP_EXTENDED(priv->capabilities) &&
-		    (SYN_CAP_FOUR_BUTTON(priv->capabilities))) {
-			hw->up = ((buf[3] & 0x01)) ? 1 : 0;
-			if (hw->left)
-				hw->up = !hw->up;
-			hw->down = ((buf[3] & 0x02)) ? 1 : 0;
-			if (hw->right)
-				hw->down = !hw->down;
+
+		if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+			hw->up   = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+			hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
 		}
+
 		if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
-		    ((buf[3] & 2) ? !hw->right : hw->right)) {
+		    ((buf[0] ^ buf[3]) & 0x02)) {
 			switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
 			default:
 				/*
@@ -490,17 +485,17 @@ static void synaptics_parse_hw_state(uns
 				 */
 				break;
 			case 8:
-				hw->b7 = ((buf[5] & 0x08)) ? 1 : 0;
-				hw->b6 = ((buf[4] & 0x08)) ? 1 : 0;
+				hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0;
+				hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0;
 			case 6:
-				hw->b5 = ((buf[5] & 0x04)) ? 1 : 0;
-				hw->b4 = ((buf[4] & 0x04)) ? 1 : 0;
+				hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0;
+				hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0;
 			case 4:
-				hw->b3 = ((buf[5] & 0x02)) ? 1 : 0;
-				hw->b2 = ((buf[4] & 0x02)) ? 1 : 0;
+				hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0;
+				hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0;
 			case 2:
-				hw->b1 = ((buf[5] & 0x01)) ? 1 : 0;
-				hw->b0 = ((buf[4] & 0x01)) ? 1 : 0;
+				hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0;
+				hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0;
 			}
 		}
 	} else {
@@ -525,6 +520,7 @@ static void synaptics_process_packet(str
 	struct synaptics_hw_state hw;
 	int num_fingers;
 	int finger_width;
+	int i;
 
 	synaptics_parse_hw_state(psmouse->packet, priv, &hw);
 
@@ -570,32 +566,17 @@ static void synaptics_process_packet(str
 	input_report_key(dev, BTN_TOOL_DOUBLETAP, num_fingers == 2);
 	input_report_key(dev, BTN_TOOL_TRIPLETAP, num_fingers == 3);
 
-	input_report_key(dev, BTN_LEFT,    hw.left);
-	input_report_key(dev, BTN_RIGHT,   hw.right);
-	input_report_key(dev, BTN_FORWARD, hw.up);
-	input_report_key(dev, BTN_BACK,    hw.down);
-	if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
-		switch(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
-		default:
-			/*
-			 * if nExtBtn is greater than 8 it should be considered
-			 * invalid and treated as 0
-			 */
-			break;
-		case 8:
-			input_report_key(dev, BTN_7,       hw.b7);
-			input_report_key(dev, BTN_6,       hw.b6);
-		case 6:
-			input_report_key(dev, BTN_5,       hw.b5);
-			input_report_key(dev, BTN_4,       hw.b4);
-		case 4:
-			input_report_key(dev, BTN_3,       hw.b3);
-			input_report_key(dev, BTN_2,       hw.b2);
-		case 2:
-			input_report_key(dev, BTN_1,       hw.b1);
-			input_report_key(dev, BTN_0,       hw.b0);
-			break;
-		}
+	input_report_key(dev, BTN_LEFT, hw.left);
+	input_report_key(dev, BTN_RIGHT, hw.right);
+
+	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+		input_report_key(dev, BTN_FORWARD, hw.up);
+		input_report_key(dev, BTN_BACK, hw.down);
+	}
+
+	for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++)
+		input_report_key(dev, BTN_0 + i, hw.ext_buttons & (1 << i));
+
 	input_sync(dev);
 }
 
diff -puN drivers/input/mouse/synaptics.h~new-set-of-input-patches-synaptics-cleanup drivers/input/mouse/synaptics.h
--- 25/drivers/input/mouse/synaptics.h~new-set-of-input-patches-synaptics-cleanup	2004-04-21 00:22:20.630898912 -0700
+++ 25-akpm/drivers/input/mouse/synaptics.h	2004-04-21 00:22:20.636898000 -0700
@@ -50,7 +50,7 @@ extern void synaptics_reset(struct psmou
 #define SYN_CAP_MULTIFINGER(c)		((c) & (1 << 1))
 #define SYN_CAP_PALMDETECT(c)		((c) & (1 << 0))
 #define SYN_CAP_VALID(c)		((((c) & 0x00ff00) >> 8) == 0x47)
-#define SYN_EXT_CAP_REQUESTS(c)		((((c) & 0x700000) >> 20) == 1)
+#define SYN_EXT_CAP_REQUESTS(c)		(((c) & 0x700000) >> 20)
 #define SYN_CAP_MULTI_BUTTON_NO(ec)	(((ec) & 0x00f000) >> 12)
 
 /* synaptics modes query bits */
@@ -86,18 +86,11 @@ struct synaptics_hw_state {
 	int y;
 	int z;
 	int w;
-	int left;
-	int right;
-	int up;
-	int down;
-	int b0;
-	int b1;
-	int b2;
-	int b3;
-	int b4;
-	int b5;
-	int b6;
-	int b7;
+	unsigned int left:1;
+	unsigned int right:1;
+	unsigned int up:1;
+	unsigned int down:1;
+	unsigned char ext_buttons;
 };
 
 struct synaptics_data {

_