Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 Nov 2009 17:48:25 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r199888 - head/sys/dev/adb
Message-ID:  <200911281748.nASHmPOx062624@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sat Nov 28 17:48:25 2009
New Revision: 199888
URL: http://svn.freebsd.org/changeset/base/199888

Log:
  Add support for interpreting taps on ADB touchpads as a button click.
  
  Submitted by:	Andreas Tobler <andreast-list at fgznet dot ch>
  MFC after:	2 weeks

Modified:
  head/sys/dev/adb/adb.h
  head/sys/dev/adb/adb_bus.c
  head/sys/dev/adb/adb_mouse.c

Modified: head/sys/dev/adb/adb.h
==============================================================================
--- head/sys/dev/adb/adb.h	Sat Nov 28 17:44:57 2009	(r199887)
+++ head/sys/dev/adb/adb.h	Sat Nov 28 17:48:25 2009	(r199888)
@@ -69,6 +69,7 @@ uint8_t adb_get_device_handler(device_t 
 uint8_t adb_set_device_handler(device_t dev, uint8_t newhandler);
 
 size_t	adb_read_register(device_t dev, u_char reg, void *data);
+size_t	adb_write_register(device_t dev, u_char reg, size_t len, void *data);
 
 /* Bits for implementing ADB host bus adapters */
 extern devclass_t adb_devclass;

Modified: head/sys/dev/adb/adb_bus.c
==============================================================================
--- head/sys/dev/adb/adb_bus.c	Sat Nov 28 17:44:57 2009	(r199887)
+++ head/sys/dev/adb/adb_bus.c	Sat Nov 28 17:48:25 2009	(r199888)
@@ -402,3 +402,21 @@ adb_read_register(device_t dev, u_char r
 	return (result);
 }
 
+size_t 
+adb_write_register(device_t dev, u_char reg, size_t len, void *data) 
+{
+	struct adb_softc *sc;
+	struct adb_devinfo *dinfo;
+	size_t result;
+	
+	dinfo = device_get_ivars(dev);
+	sc = device_get_softc(device_get_parent(dev));
+	
+	result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
+		   ADB_COMMAND_LISTEN, reg, len, (u_char *)data, NULL);
+	
+	result = adb_send_raw_packet_sync(sc->sc_dev,dinfo->address,
+	           ADB_COMMAND_TALK, reg, 0, NULL, NULL);
+
+	return (result);
+}

Modified: head/sys/dev/adb/adb_mouse.c
==============================================================================
--- head/sys/dev/adb/adb_mouse.c	Sat Nov 28 17:44:57 2009	(r199887)
+++ head/sys/dev/adb/adb_mouse.c	Sat Nov 28 17:48:25 2009	(r199888)
@@ -35,6 +35,7 @@
 #include <sys/poll.h>
 #include <sys/condvar.h>
 #include <sys/selinfo.h>
+#include <sys/sysctl.h>
 #include <sys/uio.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
@@ -51,6 +52,8 @@
 static int adb_mouse_probe(device_t dev);
 static int adb_mouse_attach(device_t dev);
 static int adb_mouse_detach(device_t dev);
+static void adb_init_trackpad(device_t dev);
+static int adb_tapping_sysctl(SYSCTL_HANDLER_ARGS);
 
 static d_open_t  ams_open;
 static d_close_t ams_close;
@@ -77,6 +80,8 @@ struct adb_mouse_softc {
 	u_char id[4];
 
 	int buttons;
+	u_int sc_tapping;
+	int button_buf;
 	int last_buttons;
 	int xdelta, ydelta;
 
@@ -167,6 +172,8 @@ adb_mouse_attach(device_t dev) 
 	sc->mode.packetsize = 5;
 
 	sc->buttons = 0;
+	sc->sc_tapping = 0;
+	sc->button_buf = 0;
 	sc->last_buttons = 0;
 	sc->packet_read_len = 0;
 
@@ -205,6 +212,7 @@ adb_mouse_attach(device_t dev) 
 		case 3:
 			sc->flags |= AMS_TOUCHPAD;
 			sc->hw.type = MOUSE_PAD;
+			adb_init_trackpad(dev);
 			description = "Touchpad";
 			break;
 		}
@@ -259,6 +267,70 @@ adb_mouse_detach(device_t dev) 
 	return (0);
 }
 
+static void
+adb_init_trackpad(device_t dev)
+{
+	struct adb_mouse_softc *sc;
+	struct sysctl_ctx_list *ctx;
+	struct sysctl_oid *tree;
+
+	size_t r1_len;
+	u_char r1[8];
+	u_char r2[8];
+
+	sc = device_get_softc(dev);
+
+	r1_len = adb_read_register(dev, 1, r1);
+
+	/* An Extended Mouse register1 must return 8 bytes. */
+	if (r1_len != 8)
+		return;
+
+	if((r1[6] != 0x0d))
+	{
+		r1[6] = 0x0d;
+		
+		adb_write_register(dev, 1, 8, r1); 
+      
+		r1_len = adb_read_register(dev, 1, r1);
+      
+		if (r1[6] != 0x0d)
+		{
+			device_printf(dev, "ADB Mouse = 0x%x "
+				      "(non-Extended Mode)\n", r1[6]);
+			return;
+		} else {
+			device_printf(dev, "ADB Mouse = 0x%x "
+				      "(Extended Mode)\n", r1[6]);
+			
+			/* Set ADB Extended Features to default values,
+			   enabled. */
+			r2[0] = 0x19; /* Clicking: 0x19 disabled 0x99 enabled */
+			r2[1] = 0x94; /* Dragging: 0x14 disabled 0x94 enabled */
+			r2[2] = 0x19;
+			r2[3] = 0xff; /* DragLock: 0xff disabled 0xb2 enabled */
+			r2[4] = 0xb2;
+			r2[5] = 0x8a;
+			r2[6] = 0x1b;
+		       
+			r2[7] = 0x57;  /* 0x57 bits 3:0 for W mode */
+			
+			adb_write_register(dev, 2, 8, r2);
+			
+		}
+	}
+
+	/*
+	 * Set up sysctl
+	 */
+	ctx = device_get_sysctl_ctx(dev);
+	tree = device_get_sysctl_tree(dev);
+	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "tapping",
+			CTLTYPE_INT | CTLFLAG_RW, sc, 0, adb_tapping_sysctl,
+			"I", "Tapping the pad causes button events");
+	return;
+}
+
 static u_int 
 adb_mouse_receive_packet(device_t dev, u_char status, u_char command, 
     u_char reg, int len, u_char *data) 
@@ -266,7 +338,7 @@ adb_mouse_receive_packet(device_t dev, u
 	struct adb_mouse_softc *sc;
 	int i = 0;
 	int xdelta, ydelta;
-	int buttons;
+	int buttons, tmp_buttons;
 
 	sc = device_get_softc(dev);
 
@@ -298,6 +370,30 @@ adb_mouse_receive_packet(device_t dev, u
 	if (ydelta & (0x40 << 3*(len-2)))
 		ydelta |= 0xffffffc0 << 3*(len - 2);
 
+	if ((sc->flags & AMS_TOUCHPAD) && (sc->sc_tapping == 1)) {
+		tmp_buttons = buttons;
+		if (buttons == 0x12) {
+			/* Map a double tap on button 3.
+			   Keep the button state for the next sequence.
+			   A double tap sequence is followed by a single tap
+			   sequence.
+			*/
+			tmp_buttons = 0x3;
+			sc->button_buf = tmp_buttons;
+		} else if (buttons == 0x2) {
+			/* Map a single tap on button 2. But only if it is
+			   not a successor from a double tap.
+			*/
+			if (sc->button_buf != 0x3) 
+				tmp_buttons = 0x2;
+			else
+				tmp_buttons = 0;
+
+			sc->button_buf = 0;
+		}
+		buttons = tmp_buttons;
+	}
+
 	/*
 	 * Some mice report high-numbered buttons on the wrong button number,
 	 * so set the highest-numbered real button as pressed if there are
@@ -554,3 +650,36 @@ ams_ioctl(struct cdev *dev, u_long cmd, 
 	return (0);
 }
 
+static int
+adb_tapping_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct adb_mouse_softc *sc = arg1;
+	device_t dev;
+        int error;
+	u_char r2[8];
+	u_int tapping;
+
+	dev = sc->sc_dev;
+	tapping = sc->sc_tapping;
+
+	error = sysctl_handle_int(oidp, &tapping, 0, req);
+
+	if (error || !req->newptr)
+		return (error);
+
+	if (tapping == 1) {
+		adb_read_register(dev, 2, r2);
+		r2[0] = 0x99; /* enable tapping. */
+		adb_write_register(dev, 2, 8, r2);
+                sc->sc_tapping = 1;
+	} else if (tapping == 0) {
+		adb_read_register(dev, 2, r2);
+		r2[0] = 0x19; /* disable tapping. */
+		adb_write_register(dev, 2, 8, r2);
+		sc->sc_tapping = 0;
+	}
+        else
+		return (EINVAL);
+
+	return (0);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911281748.nASHmPOx062624>