Source-Changes-HG archive

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

[src/trunk]: src Add basic support for tap detection, emulating a left-click.



details:   https://anonhg.NetBSD.org/src/rev/03813010da6d
branches:  trunk
changeset: 339195:03813010da6d
user:      bouyer <bouyer%NetBSD.org@localhost>
date:      Fri Jul 03 14:18:18 2015 +0000

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

diffstat:

 share/man/man4/btmagic.4    |    9 ++-
 sys/dev/bluetooth/btmagic.c |  112 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 115 insertions(+), 6 deletions(-)

diffs (242 lines):

diff -r 6ce2848dcb73 -r 03813010da6d share/man/man4/btmagic.4
--- a/share/man/man4/btmagic.4  Fri Jul 03 13:17:20 2015 +0000
+++ b/share/man/man4/btmagic.4  Fri Jul 03 14:18:18 2015 +0000
@@ -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 @@
 .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
diff -r 6ce2848dcb73 -r 03813010da6d sys/dev/bluetooth/btmagic.c
--- a/sys/dev/bluetooth/btmagic.c       Fri Jul 03 13:17:20 2015 +0000
+++ b/sys/dev/bluetooth/btmagic.c       Fri Jul 03 14:18:18 2015 +0000
@@ -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 @@
        /* 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_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_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 @@
         */
        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 @@
        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 @@
                        (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 @@
                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 @@
        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 @@
                        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 @@
                                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 @@
                                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 @@
                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);
+}



Home | Main Index | Thread Index | Old Index