Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/pckbport Significant update to the synaptics touchpa...
details: https://anonhg.NetBSD.org/src/rev/e9431105a64a
branches: trunk
changeset: 989946:e9431105a64a
user: blymn <blymn%NetBSD.org@localhost>
date: Thu Oct 21 04:49:28 2021 +0000
description:
Significant update to the synaptics touchpad driver.
* Accumulate packets for primary, secondary, finger count packets
before handing off to pms_synaptics_process_packet. This means
that both primary and, possibly, secondary finger locations will
be processed at the same time. Previously the processing each
packet as it arrived.
* Fix the secondary finger position reporting, there was an off by
one in the shifts when decoding which effectively halved the
reported position.
* For a clickpad, make the emulated button region "dead" so that finger
movements in this region are ignored. This makes it easier to click
a button without accidentally repositioning the cursor. There is a
sysctl variable "button_region_movement_enable" that will allow
these finger movements to be reported if this is desirable.
* Reset the finger ballistics when the number of fingers changes. This
stops the annoying position jumps when a second finger touch is added
to or removed from the touchpad.
* Add a level argument to the DPRINTF macro so one can choose their
level of debug spam via the debug sysctl variable.
diffstat:
sys/dev/pckbport/synaptics.c | 606 ++++++++++++++++++++++++++++++++-------
sys/dev/pckbport/synapticsvar.h | 16 +-
2 files changed, 496 insertions(+), 126 deletions(-)
diffs (truncated from 980 to 300 lines):
diff -r 9f09205bb840 -r e9431105a64a sys/dev/pckbport/synaptics.c
--- a/sys/dev/pckbport/synaptics.c Thu Oct 21 04:47:57 2021 +0000
+++ b/sys/dev/pckbport/synaptics.c Thu Oct 21 04:49:28 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: synaptics.c,v 1.72 2021/09/28 06:16:13 nia Exp $ */
+/* $NetBSD: synaptics.c,v 1.73 2021/10/21 04:49:28 blymn Exp $ */
/*
* Copyright (c) 2005, Steve C. Woodford
@@ -48,7 +48,7 @@
#include "opt_pms.h"
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.72 2021/09/28 06:16:13 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: synaptics.c,v 1.73 2021/10/21 04:49:28 blymn Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -79,11 +79,14 @@
signed short sp_x; /* Unscaled absolute X/Y coordinates */
signed short sp_y;
u_char sp_z; /* Z (pressure) */
+ signed short sp_sx; /* Unscaled absolute X/Y coordinates */
+ signed short sp_sy; /* for secondary finger */
+ u_char sp_sz; /* Z (pressure) */
u_char sp_w; /* W (contact patch width) */
- signed short sp_sx; /* Secondary finger unscaled absolute */
- /* X/Y coordinates */
- signed short sp_xy;
- u_char sp_finger; /* 0 for primary, 1 for secondary */
+ u_char sp_primary; /* seen primary finger packet */
+ u_char sp_secondary; /* seen secondary finger packet */
+ u_char sp_finger_status; /* seen extended finger packet */
+ u_char sp_finger_count; /* number of fingers seen */
char sp_left; /* Left mouse button status */
char sp_right; /* Right mouse button status */
char sp_middle; /* Middle button status (possibly emulated) */
@@ -121,12 +124,13 @@
static int synaptics_max_speed_z = 2;
static int synaptics_movement_threshold = 4;
static int synaptics_movement_enable = 1;
+static int synaptics_button_region_movement = 1;
static bool synaptics_aux_mid_button_scroll = TRUE;
static int synaptics_debug = 0;
-#define DPRINTF(SC, FMT, ARGS...) do \
+#define DPRINTF(LEVEL, SC, FMT, ARGS...) do \
{ \
- if (synaptics_debug) { \
+ if (synaptics_debug >= LEVEL) { \
struct pms_softc *_dprintf_psc = \
container_of((SC), struct pms_softc, u.synaptics); \
device_printf(_dprintf_psc->sc_dev, FMT, ##ARGS); \
@@ -157,8 +161,16 @@
static int synaptics_max_speed_z_nodenum;
static int synaptics_movement_threshold_nodenum;
static int synaptics_movement_enable_nodenum;
+static int synaptics_button_region_movement_nodenum;
static int synaptics_aux_mid_button_scroll_nodenum;
+/*
+ * This holds the processed packet data, it is global because multiple
+ * packets from the trackpad may be processed when handling multiple
+ * fingers on the trackpad to gather all the data.
+ */
+static struct synaptics_packet packet;
+
static int
synaptics_poll_cmd(struct pms_softc *psc, ...)
{
@@ -490,6 +502,10 @@
(sc->flags & SYN_FLAG_HAS_ADV_GESTURE_MODE))
synaptics_special_write(psc, SYNAPTICS_WRITE_DELUXE_3, 0x3);
+ /* Disable motion in the button region for clickpads */
+ if(sc->flags & SYN_FLAG_HAS_ONE_BUTTON_CLICKPAD)
+ synaptics_button_region_movement = 0;
+
sc->up_down = 0;
sc->prev_fingers = 0;
sc->gesture_start_x = sc->gesture_start_y = 0;
@@ -497,11 +513,14 @@
sc->gesture_tap_packet = 0;
sc->gesture_type = 0;
sc->gesture_buttons = 0;
+ sc->total_packets = 0;
for (i = 0; i < SYN_MAX_FINGERS; i++) {
sc->rem_x[i] = sc->rem_y[i] = sc->rem_z[i] = 0;
- sc->movement_history[i] = 0;
}
sc->button_history = 0;
+
+ /* clear the packet decode structure */
+ memset(&packet, 0, sizeof(packet));
}
void
@@ -766,6 +785,18 @@
if ((rc = sysctl_createv(clog, 0, NULL, &node,
CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+ CTLTYPE_INT, "button_region_movement_enable",
+ SYSCTL_DESCR("Enable movement within clickpad button region"),
+ pms_sysctl_synaptics_verify, 0,
+ &synaptics_button_region_movement,
+ 0, CTL_HW, root_num, CTL_CREATE,
+ CTL_EOL)) != 0)
+ goto err;
+
+ synaptics_button_region_movement_nodenum = node->sysctl_num;
+
+ if ((rc = sysctl_createv(clog, 0, NULL, &node,
+ CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
CTLTYPE_INT, "button_boundary",
SYSCTL_DESCR("Top edge of button area"),
pms_sysctl_synaptics_verify, 0,
@@ -904,6 +935,10 @@
if (t < 0 || t > 1)
return (EINVAL);
} else
+ if (node.sysctl_num == synaptics_button_region_movement_nodenum) {
+ if (t < 0 || t > 1)
+ return (EINVAL);
+ } else
if (node.sysctl_num == synaptics_aux_mid_button_scroll_nodenum) {
if (t < 0 || t > 1)
return (EINVAL);
@@ -915,6 +950,75 @@
return (0);
}
+/*
+ * Extract the number of fingers from the current packet and return
+ * it to the caller.
+ */
+static unsigned
+pms_synaptics_get_fingers(struct pms_softc *psc, u_char w, short z)
+{
+ struct synaptics_softc *sc = &psc->u.synaptics;
+ unsigned short ew_mode;
+ unsigned fingers;
+
+ fingers = 0;
+
+
+ /*
+ * If w is zero and z says no fingers then return
+ * no fingers, w == can also mean 2 fingers... confusing.
+ */
+ if (w == 0 && z == SYNAPTICS_FINGER_NONE)
+ return 0;
+
+ if ((sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) &&
+ (w == SYNAPTICS_WIDTH_EXTENDED_W)) {
+ ew_mode = psc->packet[5] >> 4;
+ switch (ew_mode)
+ {
+ case SYNAPTICS_EW_WHEEL:
+ break;
+
+ case SYNAPTICS_EW_SECONDARY_FINGER:
+ /* to get here we must have 2 fingers at least */
+ fingers = 2;
+ break;
+
+ case SYNAPTICS_EW_FINGER_STATUS:
+ fingers = psc->packet[1] & 0x0f;
+ break;
+
+ default:
+ aprint_error_dev(psc->sc_dev,
+ "invalid extended w mode %d\n",
+ ew_mode);
+ return 0; /* pretend there are no fingers */
+ }
+ } else {
+
+ fingers = 1;
+
+ /*
+ * If SYN_FLAG_HAS_MULTI_FINGER is set then check
+ * sp_w is below SYNAPTICS_WIDTH_FINGER_MIN, if it is
+ * then this will be the finger count.
+ *
+ * There are a couple of "special" values otherwise
+ * just punt with one finger, if this really is a palm
+ * then it will be caught later.
+ */
+ if (sc->flags & SYN_FLAG_HAS_MULTI_FINGER) {
+ if (w == SYNAPTICS_WIDTH_TWO_FINGERS)
+ fingers = 2;
+ else if (w == SYNAPTICS_WIDTH_THREE_OR_MORE)
+ fingers = 3;
+ }
+
+ }
+
+ return fingers;
+}
+
/* Masks for the first byte of a packet */
#define PMS_LBUTMASK 0x01
#define PMS_RBUTMASK 0x02
@@ -924,18 +1028,24 @@
pms_synaptics_parse(struct pms_softc *psc)
{
struct synaptics_softc *sc = &psc->u.synaptics;
- struct synaptics_packet sp;
+ struct synaptics_packet nsp;
char new_buttons, ew_mode;
+ unsigned v, primary_finger, secondary_finger;
- memset(&sp, 0, sizeof(sp));
+ sc->total_packets++;
+
+ memcpy(&nsp, &packet, sizeof(packet));
/* Width of finger */
- sp.sp_w = ((psc->packet[0] & 0x30) >> 2) +
- ((psc->packet[0] & 0x04) >> 1) +
- ((psc->packet[3] & 0x04) >> 2);
- sp.sp_finger = 0;
+ nsp.sp_w = ((psc->packet[0] & 0x30) >> 2)
+ + ((psc->packet[0] & 0x04) >> 1)
+ + ((psc->packet[3] & 0x04) >> 2);
+
+ v = 0;
+ primary_finger = 0;
+ secondary_finger = 0;
if ((sc->flags & SYN_FLAG_HAS_EXTENDED_WMODE) &&
- (sp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W)) {
+ (nsp.sp_w == SYNAPTICS_WIDTH_EXTENDED_W)) {
ew_mode = psc->packet[5] >> 4;
switch (ew_mode)
{
@@ -947,25 +1057,41 @@
case SYNAPTICS_EW_SECONDARY_FINGER:
/* parse the second finger report */
- sp.sp_finger = 1; /* just one other finger for now */
- sp.sp_x = psc->packet[1]
- + ((psc->packet[4] & 0x0f) << 8);
- sp.sp_y = psc->packet[2]
- + ((psc->packet[4] & 0xf0) << 4);
- sp.sp_z = (psc->packet[3] & 0x30)
- + (psc->packet[5] & 0x0f);
+ nsp.sp_secondary = 1;
+
+ nsp.sp_sx = ((psc->packet[1] & 0xfe) << 1)
+ + ((psc->packet[4] & 0x0f) << 9);
+ nsp.sp_sy = ((psc->packet[2] & 0xfe) << 1)
+ + ((psc->packet[4] & 0xf0) << 5);
+ nsp.sp_sz = (psc->packet[3] & 0x30)
+ + ((psc->packet[5] & 0x0e) << 1);
+
+ /* work out the virtual finger width */
+ v = 8 + (psc->packet[1] & 0x01) +
+ ((psc->packet[2] & 0x01) << 1) +
+ ((psc->packet[5] & 0x01) << 2);
/* keep same buttons down as primary */
- sp.sp_left = sc->button_history & PMS_LBUTMASK;
- sp.sp_middle = sc->button_history & PMS_MBUTMASK;
- sp.sp_right = sc->button_history & PMS_RBUTMASK;
+ nsp.sp_left = sc->button_history & PMS_LBUTMASK;
+ nsp.sp_middle = sc->button_history & PMS_MBUTMASK;
+ nsp.sp_right = sc->button_history & PMS_RBUTMASK;
break;
case SYNAPTICS_EW_FINGER_STATUS:
- /* reports which finger is primary/secondary
- * ignore for now.
+ /* This works but what is it good for?
+ * it gives us an index of the primary/secondary
+ * fingers but no other packets pass this
+ * index.
+ *
+ * XXX Park this, possibly handle a finger
+ * XXX change if indexes change.
*/
- return;
+ primary_finger = psc->packet[2];
+ secondary_finger = psc->packet[4];
+ nsp.sp_finger_status = 1;
+ nsp.sp_finger_count = pms_synaptics_get_fingers(psc,
+ nsp.sp_w, nsp.sp_z);
+ goto skip_position;
default:
aprint_error_dev(psc->sc_dev,
@@ -974,15 +1100,73 @@
return;
}
} else {
+ nsp.sp_primary = 1;
- /* Absolute X/Y coordinates of finger */
- sp.sp_x = psc->packet[4] + ((psc->packet[1] & 0x0f) << 8) +
- ((psc->packet[3] & 0x10) << 8);
- sp.sp_y = psc->packet[5] + ((psc->packet[1] & 0xf0) << 4) +
Home |
Main Index |
Thread Index |
Old Index