Skip to contentSkip to conversation

[2.5.68] [BUG #18] Add Synaptics touchpad tweaking to psmouse driver

PATCH In review Stuffed Crust 3 participants 5 messages Apr 22, 2003 – Apr 23, 2003

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 [2.5.68] [BUG #18] Add Synaptics touchpad tweaking to psmouse driver

One of the side-effects of the new input layer is that the old usermode tools for manipulating the touchpad configuration don't work any more.

Most importantly, the ability to disable the tap-to-click "feature". And this has been long-recognized, as bug #18. :)

So, here's my crack at scratching this itch. it defaults to disabling the tap-to-click, but there's a module parameter to re-enable it.

I started writing this from the perspective of a full-native synaptics driver, using the absolute mode of operation, which will let us do all sorts of yummy things like corner taps and virtual scroll wheels and sensitivity and whatnot... Anyone else working on this, before I wade further in?

All of the new code is wrapped in #ifdef SYNAPTICS.

It should work on all models of the touchpad, old and new, but I've only tested this on my rev5.7 touchpad (Dell Inspiron 4100)

Feedback welcome!

- Pizza

Signature · 3 lines
Solomon Peachy                                   pizza@f*cktheusers.org
                                                           ICQ #1318444
Quidquid latine dictum sit, altum viditur                 Melbourne, FL
psmouse.c renamed from psmouse.ORIG +192 -0
@@ -10,6 +10,11 @@
  * the Free Software Foundation.
  */
 
+/* 
+ * Initial Snaptics support by Solomon Peachy ([email protected])
+ */
+#define SYNAPTICS
+
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -25,6 +30,11 @@
 
 static int psmouse_noext;
 
+#ifdef SYNAPTICS
+static int synaptics_tap = 0;
+MODULE_PARM(synaptics_tap, "1i");
+#endif
+
 #define PSMOUSE_CMD_SETSCALE11	0x00e6
 #define PSMOUSE_CMD_SETRES	0x10e8
 #define PSMOUSE_CMD_GETINFO	0x03e9
@@ -33,6 +43,7 @@
 #define PSMOUSE_CMD_GETID	0x02f2
 #define PSMOUSE_CMD_SETRATE	0x10f3
 #define PSMOUSE_CMD_ENABLE	0x00f4
+#define PSMOUSE_CMD_DISABLE	0x00f5
 #define PSMOUSE_CMD_RESET_DIS	0x00f6
 #define PSMOUSE_CMD_RESET_BAT	0x02ff
 
@@ -40,6 +51,52 @@
 #define PSMOUSE_RET_ACK		0xfa
 #define PSMOUSE_RET_NAK		0xfe
 
+#ifdef SYNAPTICS
+
+/* Synaptics special queries */
+#define STP_QRY_IDENTIFY	0x00
+#define STP_QRY_READ_MODES	0x01
+#define STP_QRY_READ_CAPS	0x02
+#define STP_QRY_READ_MODEL_ID	0x03
+#define STP_QRY_READ_SN_PREFIX	0x06
+#define STP_QRY_READ_SN_SUFFIX	0x07
+#define STP_QRY_READ_RES	0x08
+
+/* Model ID bits */
+#define STP_INFO_ROT180(id)	(((id) & 0x800000) >> 23)
+#define STP_INFO_PORTRAIT(id)	(((id) & 0x400000) >> 22)
+#define STP_INFO_SENSOR(id)	(((id) & 0x3F0000) >> 16)
+#define STP_INFO_HARDWARE(id)	(((id) & 0x00FE00) >> 9)
+#define STP_INFO_NEW_ABS(id)	(((id) & 0x000080) >> 7)
+#define STP_INFO_CAP_PEN(id)	(((id) & 0x000040) >> 6)
+#define STP_INFO_SIMPLE_CMD(id)	(((id) & 0x000020) >> 5)
+#define STP_INFO_GEOMETRY(id)	 ((id) & 0x00000F)
+
+#define STP_SET_MODE_ABSOLUTE(m, a)	(((m) &~ 0x80) | ((a) << 7))
+#define STP_SET_MODE_RATE(m, a)		(((m) &~ 0x40) | ((a) << 6))
+#define STP_SET_MODE_SLEEP(m, a)	(((m) &~ 0x08) | ((a) << 3))
+#define STP_SET_MODE_GESTURE(m, a)	(((m) &~ 0x04) | ((!a) << 2))
+#define STP_SET_MODE_PACKSIZE(m, a)	(((m) &~ 0x02) | ((a) << 1))
+#define STP_SET_MODE_WMODE(m, a)	(((m) &~ 0x01) | (a))
+
+#define STP_SET_OMODE_CORNER(m, a)	(((m) &~ 0x80000000) | ((a) << 31))
+#define STP_SET_OMODE_Z_THRESH(m, a)	(((m) &~ 0x70000000) | ((a) << 28))
+#define STP_SET_OMODE_TAP_MODE(m, a)	(((m) &~ 0x0C000000) | ((a) << 26))
+#define STP_SET_OMODE_EDGE_MOTN(m, a)	(((m) &~ 0x03000000) | ((a) << 24))
+#define STP_SET_OMODE_ABSOLUTE(m, a)	(((m) &~ 0x00800000) | ((a) << 23))
+#define STP_SET_OMODE_RATE(m, a)	(((m) &~ 0x00400000) | ((a) << 22))
+#define STP_SET_OMODE_BAUD(m, a)	(((m) &~ 0x00080000) | ((a) << 19))
+#define STP_SET_OMODE_3_BUTTON(m, a)	(((m) &~ 0x00040000) | ((a) << 18))
+#define STP_SET_OMODE_MIDDLE(m, a)	(((m) &~ 0x00020000) | ((a) << 17))
+#define STP_SET_OMODE_HOP(m, a)		(((m) &~ 0x00010000) | ((a) << 16))
+#define STP_SET_OMODE_RIGHT_MGN(m, a)	(((m) &~ 0x0000F000) | ((a) << 12))
+#define STP_SET_OMODE_LEFT_MGN(m, a)	(((m) &~ 0x00000F00) | ((a) << 8))
+#define STP_SET_OMODE_TOP_MGN(m, a)	(((m) &~ 0x000000F0) | ((a) << 4))
+#define STP_SET_OMODE_BOTTOM_MGN(m, a)	(((m) &~ 0x0000000F) |  (a))
+#define QUAD_MODE_BYTE		0x0302
+
+#endif
+
 struct psmouse {
 	struct input_dev dev;
 	struct serio *serio;
@@ -57,8 +114,22 @@
 	char error;
 	char devname[64];
 	char phys[32];
+
+#ifdef SYNAPTICS
+	unsigned int fw_version;
+	unsigned int single_mode_byte;
+	unsigned int model_id;
+	unsigned int modes;
+	unsigned int caps;
+#endif
 };
 
+#ifdef SYNAPTICS
+static void synaptics_command(struct psmouse *psmouse, unsigned char cmd);
+static void synaptics_set_mode(struct psmouse *psmouse, unsigned int mode);
+unsigned int synaptics_get_mode(struct psmouse *psmouse);
+#endif
+
 #define PSMOUSE_PS2	1
 #define PSMOUSE_PS2PP	2
 #define PSMOUSE_PS2TPP	3
@@ -345,6 +416,54 @@
                   thing up. */
                psmouse->vendor = "Synaptics";
                psmouse->name = "TouchPad";
+
+#ifdef SYNAPTICS
+	       param[0] = 0;
+	       synaptics_command(psmouse, STP_QRY_IDENTIFY);
+	       psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+	       psmouse->fw_version = ((param[2] & 0x0f) << 8) | param[0];
+
+	       synaptics_command(psmouse, STP_QRY_READ_MODEL_ID);
+	       psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+
+	       psmouse->model_id = ((param[1] & 0x1) ? 0x1 :
+				    (((unsigned int) param[0] << 16) |
+				     ((unsigned int) param[1] << 8) |
+				     ((unsigned int) param[2])));
+
+	       psmouse->single_mode_byte = STP_INFO_SIMPLE_CMD (psmouse->model_id);
+	       /* Fetch capabilities */
+	       synaptics_command(psmouse, STP_QRY_READ_MODEL_ID);
+	       psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+	       psmouse->caps = (((unsigned int) param[0] << 8) | 
+				(unsigned int) param[2]);
+
+	       printk(KERN_INFO "Found Synaptics Touchpad rev %d.%d\n",
+		      (psmouse->fw_version >> 8) & 0x0f,
+		      (psmouse->fw_version & 0xff));
+
+	       /* pull the modes down */
+	       psmouse->modes = synaptics_get_mode(psmouse);
+
+	       /* Now, disable tap-to-click and enable high rate. */
+	       
+	       if (psmouse->single_mode_byte) {
+		       psmouse->modes = STP_SET_MODE_GESTURE(psmouse->modes, synaptics_tap);
+		       psmouse->modes = STP_SET_MODE_RATE(psmouse->modes, 1);
+
+		       synaptics_set_mode(psmouse, psmouse->modes);
+	       } else {
+		       psmouse->modes = STP_SET_OMODE_TAP_MODE(psmouse->modes, synaptics_tap);
+		       psmouse->modes = STP_SET_OMODE_RATE(psmouse->modes, 1);
+
+		       synaptics_set_mode(psmouse, psmouse->modes);
+	       }
+			       
+	       psmouse->modes = synaptics_get_mode(psmouse);
+#else
+	       printk(KERN_INFO "Found Synaptics touchpad, support disabled\n");
+#endif
+
                return PSMOUSE_PS2;
        }
 
@@ -682,5 +801,78 @@
 	serio_unregister_device(&psmouse_dev);
 }
 
+#ifdef SYNAPTICS
+void synaptics_command(struct psmouse *psmouse, unsigned char cmd) 
+{
+	unsigned char param[4];
+
+	param[0] = (cmd & 0xC0) >> 6;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	param[0] = (cmd & 0x30) >> 4;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	param[0] = (cmd & 0x0C) >> 2;
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+	param[0] = (cmd & 0x03);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
+}
+
+void synaptics_set_mode(struct psmouse *psmouse, unsigned int mode)
+{
+	unsigned char param[4];
+//	printk(KERN_INFO "Synaptics set mode: %08x\n", mode);
+  
+	psmouse_command(psmouse, param, PSMOUSE_CMD_DISABLE);
+	
+	if (psmouse->single_mode_byte) {
+		synaptics_command(psmouse, mode & 0xff);
+		param[0] = 20;
+		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+	} else {
+		synaptics_command(psmouse, (mode >> 24) & 0xff);
+		param[0] = 10;
+		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+		synaptics_command(psmouse, (mode >> 16) & 0xff);
+		param[0] = 20;
+		psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+		if (psmouse->fw_version < QUAD_MODE_BYTE) {
+			synaptics_command(psmouse, (mode >> 8) & 0xff);
+			param[0] = 40;
+			psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+			synaptics_command(psmouse, mode & 0xff);
+			param[0] = 60;
+			psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
+		}
+	}
+
+	psmouse_command(psmouse, param, PSMOUSE_CMD_ENABLE);
+}
+
+unsigned int synaptics_get_mode(struct psmouse *psmouse)
+{
+	unsigned char param[4];
+	unsigned int retval = 0;
+	
+	synaptics_command(psmouse, STP_QRY_READ_MODES);
+	psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+	
+	param[1] = 0;
+	
+	if (psmouse->single_mode_byte) {
+		retval = param[2];
+	} else {
+		retval = ((param[0] << 24) |
+			  (param[2] << 16));
+		
+		if (psmouse->fw_version < QUAD_MODE_BYTE) {
+			synaptics_command(psmouse, STP_QRY_READ_CAPS);
+			psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
+			retval |= ((param[0] << 8) |
+				   (param[2]));
+		} 
+	}
+	return retval;
+}
+#endif
+
 module_init(psmouse_init);
 module_exit(psmouse_exit);
#1 lore raw
Quoted 2 lines · Stuffed Crust

One of the side-effects of the new input layer is that the old usermode tools for manipulating the touchpad configuration don't work any more.

Aye. :/

Quoted 2 lines

Most importantly, the ability to disable the tap-to-click "feature". And this has been long-recognized, as bug #18. :)

Bah. I like this and use it often. :)

Quoted 1 line

Feedback welcome!

I haven't tested it mainly because it doesn't do anything useful for me yet (and, infact, reduces usability) but I'll be more then happy to test any future more general patches that you may come up with.

Signature · 6 lines
Martin's distress was in contrast to the bitter satisfaction of some
of his fellow marines as they surveyed the scene. "The Iraqis are sick
people and we are the chemotherapy," said Corporal Ryan Dupre. "I am
starting to hate this country. Wait till I get hold of a friggin' Iraqi.
No, I won't get hold of one. I'll just kill him."
	- http://www.informationclearinghouse.info/article2479.htm
#2 lore raw
Quoted 3 lines · CaT

I haven't tested it mainly because it doesn't do anything useful for me yet (and, infact, reduces usability) but I'll be more then happy to test any future more general patches that you may come up with.

Um, it doesn't reduce functionality. There's a module parameter to enable/disable the tap-to-click. :)

Any further functionality will require a much older touchpad (rev <4), and/or the use of absolute mode. But I'm working on that.

- Pizza

Signature · 3 lines
Solomon Peachy                                   pizza@f*cktheusers.org
                                                           ICQ #1318444
Quidquid latine dictum sit, altum viditur                 Melbourne, FL
#3 lore raw
In reply to Stuffed Crust
Quoted 9 lines · Stuffed Crust

One of the side-effects of the new input layer is that the old usermode tools for manipulating the touchpad configuration don't work any more.

Most importantly, the ability to disable the tap-to-click "feature". And this has been long-recognized, as bug #18. :)

So, here's my crack at scratching this itch. it defaults to disabling the tap-to-click, but there's a module parameter to re-enable it.

Quoted 7 lines

I started writing this from the perspective of a full-native synaptics driver, using the absolute mode of operation, which will let us do all sorts of yummy things like corner taps and virtual scroll wheels and sensitivity and whatnot... Anyone else working on this, before I wade further in?

All of the new code is wrapped in #ifdef SYNAPTICS.

This is messy as hell - what about copying psmouse.c, remove all that code not relevant to the touchpad and make it a driver of it's own?

#4 lore raw
Quoted 3 lines · Christoph Hellwig

This is messy as hell - what about copying psmouse.c, remove all that code not relevant to the touchpad and make it a driver of it's own?

That's my plan.

Like I said, this was the first cut. And it solves the immediate problem. The RightWay is to create a native synaptics driver, and I'm working on that, but it will be a little ways off because it's radically different.

- Pizza

Signature · 3 lines
Solomon Peachy                                   pizza@f*cktheusers.org
                                                           ICQ #1318444
Quidquid latine dictum sit, altum viditur                 Melbourne, FL