Add basic support for tap detection, emulating a left-click.
This commit is contained in:
parent
337e82ce24
commit
3c96c24fae
|
@ -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
|
||||
|
|
|
@ -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 btmagic_softc *);
|
|||
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 *, struct mbuf *);
|
|||
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 self, void *aux)
|
|||
*/
|
||||
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 self, void *aux)
|
|||
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 self, void *aux)
|
|||
(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_softc *sc, uint8_t *data, size_t len)
|
|||
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_softc *sc, uint8_t *data, size_t len)
|
|||
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_softc *sc, uint8_t *data, size_t len)
|
|||
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_softc *sc, uint8_t *data, size_t len)
|
|||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue