[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Trackpad scrolling?



* On Thu, Jun 03, 2004 at 01:08:29AM -0500, I received from dotto@uchicago.edu:
> Something I've been looking for for a while now is a trackpad driver for the 
> powerbook that would allow me to scroll on one of the edges of the trackpad. 
> Someone created sidewinder for OSX, but I haven't seen this for linux.  Seems 
> kind of strange to me...

I grabbed this patch a while ago from this list or the Gentoo
ppc forums. It doesn't apply cleanly, but with some "manual
intervention" i got it to work on every kernel I tried,
including the 2.6.6-rc2 I am using now.

-- 
Ben
--- linuxppc-2.5-benh/drivers/macintosh/adbhid.c.vanilla	2003-12-05 01:42:00.000000000 +0100
+++ linuxppc-2.5-benh/drivers/macintosh/adbhid.c	2004-01-10 11:02:14.769705832 +0100
@@ -239,6 +239,93 @@
 }
 
 static void
+emulate_relative_trackpad_mode(unsigned char *data)
+{
+	static int prev_x[16] = {-1,-1,-1,-1,-1,-1,-1,-1,
+				 -1,-1,-1,-1,-1,-1,-1,-1};
+	static int prev_y[16] = {-1,-1,-1,-1,-1,-1,-1,-1,
+				 -1,-1,-1,-1,-1,-1,-1,-1};
+	static int max_x[16] = {1400,1400,1400,1400,1400,1400,1400,1400,
+				1400,1400,1400,1400,1400,1400,1400,1400};
+	int btn1, btn2, x_axis, y_axis;
+	int rel_x, rel_y;
+	int id = (data[0] >> 4) & 0x0f;
+
+	x_axis  = (data[2] & 0x7f) | 
+	    ((data[3] & 0x07) << 7) |
+	    ((data[4] & 0x07) << 10);
+	y_axis  = (data[1] & 0x7f) | 
+	    ((data[3] & 0x70) << 3) |
+	    ((data[4] & 0x70) << 6);
+	btn1 = (!(data[1] >> 7)) & 1;
+	btn2 = (!(data[2] >> 7)) & 1;
+	/* Map btn2 (tap-click) to the left button */
+	btn1 |= btn2;
+	btn2 = 0;
+
+	if (x_axis > max_x[id])
+		max_x[id] = x_axis;
+
+	rel_x = rel_y = 0;
+	if (x_axis == 0 && y_axis == 0) {
+		/* No finger on the pad */
+		prev_x[id] = prev_y[id] = -1;
+	}
+	else if (x_axis > 0 && prev_x[id] > 0 &&
+		 y_axis > 0 && prev_y[id] > 0) {
+
+		/* "filter" the position somewhat */
+		x_axis = (prev_x[id] + x_axis) / 2;
+		y_axis = (prev_y[id] + y_axis) / 2;
+
+		rel_x = (x_axis - prev_x[id]);
+		rel_y = (y_axis - prev_y[id]);
+		/* Slow it down somewhat */
+		if (rel_x > 1 || rel_x < -1)
+			rel_x /= 2;
+		if (rel_y > 1 || rel_y < -1)
+			rel_y /= 2;
+		/* Make sure we don't overflow the 7 bits allocated
+		 * for the relative movement */
+		if (rel_x > 63)
+			rel_x = 63;
+		if (rel_x < -64)
+			rel_x = -64;
+		if (rel_y > 63)
+			rel_y = 63;
+		if (rel_y < -64)
+			rel_y = -64;
+		prev_x[id] = x_axis;
+		prev_y[id] = y_axis;
+	}
+	else {
+		prev_x[id] = x_axis;
+		prev_y[id] = y_axis;
+	}
+	/* Is the finger positioned in the scrolling area? */
+	if (x_axis > max_x[id] - 150) {
+		static int count = 0;
+
+		if (++count == 6) {
+			int diff = - rel_y;
+			count = 0;
+			if (diff > 0)
+				input_report_rel(&adbhid[id]->input, 
+						 REL_WHEEL, diff / 4 + 1);
+			else if (diff < 0)
+				input_report_rel(&adbhid[id]->input, 
+						 REL_WHEEL, diff / 4 - 1);
+		}
+		/* cancel all movment and clicks */
+		btn1 = 0;
+		rel_x = rel_y = 0;
+	}
+	/* Format the data so adbhid_mouse_input can use it */
+	data[1] = (rel_y & 0x7f) | (((!btn1) & 1) << 7);
+	data[2] = (rel_x & 0x7f) | 0x80;
+}
+
+static void
 adbhid_mouse_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
 {
 	int id = (data[0] >> 4) & 0x0f;
@@ -295,8 +382,12 @@
 	switch (adbhid[id]->mouse_kind)
 	{
 	    case ADBMOUSE_TRACKPAD:
+#ifdef CONFIG_ADB_TRACKPAD_SCROLLING
+		emulate_relative_trackpad_mode(data);
+#else
 		data[1] = (data[1] & 0x7f) | ((data[1] & data[2]) & 0x80);
 		data[2] = data[2] | 0x80;
+#endif
 		break;
 	    case ADBMOUSE_MICROSPEED:
 		data[1] = (data[1] & 0x7f) | ((data[3] & 0x01) << 7);
@@ -619,7 +710,11 @@
 
 		adbhid[id]->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 		adbhid[id]->input.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+#ifdef CONFIG_ADB_TRACKPAD_SCROLLING
+               adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
+#else
 		adbhid[id]->input.relbit[0] = BIT(REL_X) | BIT(REL_Y);
+#endif
 		break;
 
 	case ADB_MISC:
@@ -889,8 +984,12 @@
 	            r1_buffer[3],
 	            r1_buffer[4],
 	            r1_buffer[5],
+#ifdef CONFIG_ADB_TRACKPAD_SCROLLING
+		    0x00, /* Enable absolute mode */
+#else
 	            0x03, /*r1_buffer[6],*/
+#endif
 	            r1_buffer[7]);
 
 	    /* Without this flush, the trackpad may be locked up */
--- linuxppc-2.5-benh/drivers/macintosh/Kconfig.vanilla	2004-01-10 11:04:42.336272304 +0100
+++ linuxppc-2.5-benh/drivers/macintosh/Kconfig	2004-01-10 10:58:08.892084912 +0100
@@ -113,6 +113,14 @@
 
 	  If unsure, say Y.
 
+config ADB_TRACKPAD_SCROLLING
+	bool "Scrolling for ADB input devices (trackpad)"
+	depends on INPUT_ADBHID
+	help
+	  Add the scrolling feature commonly seen on Windows laptops. If you
+	  say Y here you can easily scroll in your applications by moving your
+	  finger at the right border of your trackpad.
+
 config MAC_EMUMOUSEBTN
 	bool "Support for mouse button 2+3 emulation"
 	depends on INPUT_ADBHID

Reply to: