Module Name:    src
Committed By:   bouyer
Date:           Fri Jul  3 14:18:18 UTC 2015

Modified Files:
        src/share/man/man4: btmagic.4
        src/sys/dev/bluetooth: btmagic.c

Log Message:
Add basic support for tap detection, emulating a left-click.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/share/man/man4/btmagic.4
cvs rdiff -u -r1.13 -r1.14 src/sys/dev/bluetooth/btmagic.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/share/man/man4/btmagic.4
diff -u src/share/man/man4/btmagic.4:1.4 src/share/man/man4/btmagic.4:1.5
--- src/share/man/man4/btmagic.4:1.4	Mon Apr  6 21:10:31 2015
+++ src/share/man/man4/btmagic.4	Fri Jul  3 14:18:18 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: btmagic.4,v 1.4 2015/04/06 21:10:31 wiz Exp $
+.\" $NetBSD: btmagic.4,v 1.5 2015/07/03 14:18:18 bouyer Exp $
 .\"
 .\" Copyright (c) 2010 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd April 6, 2015
+.Dd July 4, 2015
 .Dt BTMAGIC 4
 .Os
 .Sh NAME
@@ -76,7 +76,10 @@ The
 .Nm
 driver emulates 3 buttons by splitting the area at the bottom of the
 device in 3 equal zones and detects finger presence in one of these zones
-when the button is pressed.
+when the button is pressed. In addition, a tap in any area of the trackpad is interpreted as a left click. The timeout for tap detection defaults to 100ms
+and is adjustable with
+.Xr sysctl 8 .
+.Pp
 Pointer movement is reported for single-touch
 movements over the device, and scroll is reported for multi-touch movements.
 .Pp

Index: src/sys/dev/bluetooth/btmagic.c
diff -u src/sys/dev/bluetooth/btmagic.c:1.13 src/sys/dev/bluetooth/btmagic.c:1.14
--- src/sys/dev/bluetooth/btmagic.c:1.13	Thu Apr 16 19:53:19 2015
+++ src/sys/dev/bluetooth/btmagic.c	Fri Jul  3 14:18:18 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: btmagic.c,v 1.13 2015/04/16 19:53:19 christos Exp $	*/
+/*	$NetBSD: btmagic.c,v 1.14 2015/07/03 14:18:18 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -85,7 +85,7 @@
  *****************************************************************************/
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: btmagic.c,v 1.13 2015/04/16 19:53:19 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: btmagic.c,v 1.14 2015/07/03 14:18:18 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -171,6 +171,11 @@ struct btmagic_softc {
 	/* previous mouse buttons */
 	int			sc_mb_id; /* which ID selects the button */
 	uint32_t		sc_mb;
+	/* button emulation with tap */
+	int			sc_tapmb_id; /* which ID selects the button */
+	struct timeval		sc_taptime;
+	int			sc_taptimeout;
+	callout_t		sc_tapcallout;
 };
 
 /* sc_flags */
@@ -191,6 +196,8 @@ static int  btmagic_listen(struct btmagi
 static int  btmagic_connect(struct btmagic_softc *);
 static int  btmagic_sysctl_resolution(SYSCTLFN_PROTO);
 static int  btmagic_sysctl_scale(SYSCTLFN_PROTO);
+static int btmagic_tap(struct btmagic_softc *, int);
+static int  btmagic_sysctl_taptimeout(SYSCTLFN_PROTO);
 
 CFATTACH_DECL_NEW(btmagic, sizeof(struct btmagic_softc),
     btmagic_match, btmagic_attach, btmagic_detach, NULL);
@@ -220,6 +227,7 @@ static void  btmagic_input(void *, struc
 static void  btmagic_input_basic(struct btmagic_softc *, uint8_t *, size_t);
 static void  btmagic_input_magicm(struct btmagic_softc *, uint8_t *, size_t);
 static void  btmagic_input_magict(struct btmagic_softc *, uint8_t *, size_t);
+static void  btmagic_tapcallout(void *);
 
 /* report types (data[1]) */
 #define BASIC_REPORT_ID		0x10
@@ -291,8 +299,12 @@ btmagic_attach(device_t parent, device_t
 	 */
 	sc->sc_dev = self;
 	sc->sc_state = BTMAGIC_CLOSED;
+	sc->sc_mb_id = -1;
+	sc->sc_tapmb_id = -1;
 	callout_init(&sc->sc_timeout, 0);
 	callout_setfunc(&sc->sc_timeout, btmagic_timeout, sc);
+	callout_init(&sc->sc_tapcallout, 0);
+	callout_setfunc(&sc->sc_tapcallout, btmagic_tapcallout, sc);
 	sockopt_init(&sc->sc_mode, BTPROTO_L2CAP, SO_L2CAP_LM, 0);
 
 	/*
@@ -332,6 +344,7 @@ btmagic_attach(device_t parent, device_t
 	sc->sc_firm = 6;
 	sc->sc_dist = 130;
 	sc->sc_scale = 20;
+	sc->sc_taptimeout = 100;
 
 	sysctl_createv(&sc->sc_log, 0, NULL, &node,
 		0,
@@ -378,6 +391,14 @@ btmagic_attach(device_t parent, device_t
 			(void *)sc, 0,
 			CTL_HW, node->sysctl_num,
 			CTL_CREATE, CTL_EOL);
+		sysctl_createv(&sc->sc_log, 0, NULL, NULL,
+			CTLFLAG_READWRITE,
+			CTLTYPE_INT, "taptimeout",
+			"timeout for tap detection in milliseconds",
+			btmagic_sysctl_taptimeout, 0,
+			(void *)sc, 0,
+			CTL_HW, node->sysctl_num,
+			CTL_CREATE, CTL_EOL);
 	}
 
 	/*
@@ -437,6 +458,8 @@ btmagic_detach(device_t self, int flags)
 		sc->sc_ctl = NULL;
 	}
 
+	callout_halt(&sc->sc_tapcallout, bt_lock);
+	callout_destroy(&sc->sc_tapcallout);
 	callout_halt(&sc->sc_timeout, bt_lock);
 	callout_destroy(&sc->sc_timeout);
 
@@ -617,6 +640,31 @@ btmagic_sysctl_scale(SYSCTLFN_ARGS)
 	return 0;
 }
 
+/* validate tap timeout */
+static int
+btmagic_sysctl_taptimeout(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	struct btmagic_softc *sc;
+	int t, error;
+
+	node = *rnode;
+	sc = node.sysctl_data;
+
+	t = sc->sc_taptimeout;
+	node.sysctl_data = &t;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (t < max(1000 / hz, 1) || t > 999)
+		return EINVAL;
+
+	sc->sc_taptimeout = t;
+	DPRINTF(sc, "taptimeout = %u", t);
+	return 0;
+}
+
 /*****************************************************************************
  *
  *	wsmouse(4) accessops
@@ -1530,6 +1578,14 @@ btmagic_input_magict(struct btmagic_soft
 			ty = ay - sc->sc_ay[id];
 
 			if (ISSET(sc->sc_smask, __BIT(id))) {
+				struct timeval now_tv;
+				getmicrotime(&now_tv);
+				if (sc->sc_nfingers == 1 && mb == 0 &&
+				    timercmp(&sc->sc_taptime, &now_tv, >)) {
+					/* still detecting a tap */
+					continue;
+				}
+
 				if (sc->sc_nfingers == 1 || mb != 0) {
 					/* single finger moving */
 					dx += btmagic_scale(tx, &sc->sc_rx,
@@ -1548,10 +1604,22 @@ btmagic_input_magict(struct btmagic_soft
 				sc->sc_ry = 0;
 				sc->sc_rz = 0;
 				sc->sc_rw = 0;
-
 				KASSERT(!ISSET(sc->sc_smask, __BIT(id)));
 				SET(sc->sc_smask, __BIT(id));
 				sc->sc_nfingers++;
+				if (sc->sc_tapmb_id == -1 &&
+				    mb == 0 && sc->sc_mb == 0) {
+					sc->sc_tapmb_id = id;
+					getmicrotime(&sc->sc_taptime);
+					sc->sc_taptime.tv_usec +=
+					    sc->sc_taptimeout * 1000;
+					if (sc->sc_taptime.tv_usec > 1000000) {
+						sc->sc_taptime.tv_usec -=
+						    1000000;
+						sc->sc_taptime.tv_sec++;
+					}
+				}
+					
 			}
 
 			break;
@@ -1560,6 +1628,9 @@ btmagic_input_magict(struct btmagic_soft
 				CLR(sc->sc_smask, __BIT(id));
 				sc->sc_nfingers--;
 				KASSERT(sc->sc_nfingers >= 0);
+				if (id == sc->sc_tapmb_id) {
+					mb = btmagic_tap(sc, id);
+				}
 			}
 			break;
 		}
@@ -1580,3 +1651,38 @@ btmagic_input_magict(struct btmagic_soft
 		splx(s);
 	}
 }
+
+static int
+btmagic_tap(struct btmagic_softc *sc, int id)
+{
+	struct timeval now_tv;
+
+	sc->sc_tapmb_id = -1;
+	getmicrotime(&now_tv);
+	if (timercmp(&sc->sc_taptime, &now_tv, >)) {
+		/* got a tap */
+		callout_schedule(
+		    &sc->sc_tapcallout,
+		    mstohz(sc->sc_taptimeout));
+		return __BIT(0);
+	}
+	return 0;
+}
+
+static void
+btmagic_tapcallout(void *arg)
+{
+	struct btmagic_softc *sc = arg;
+	int s;
+
+	mutex_enter(bt_lock);
+	callout_ack(&sc->sc_tapcallout);
+	if ((sc->sc_mb & __BIT(0)) != 0) {
+		sc->sc_mb &= ~__BIT(0);
+		s = spltty();
+		wsmouse_input(sc->sc_wsmouse, sc->sc_mb,
+		    0, 0, 0, 0, WSMOUSE_INPUT_DELTA);
+		splx(s);
+	}
+	mutex_exit(bt_lock);
+}

Reply via email to