svn commit: r317811 - head/sys/dev/atkbdc

Vladimir Kondratyev wulf at FreeBSD.org
Thu May 4 22:47:19 UTC 2017


Author: wulf
Date: Thu May  4 22:47:18 2017
New Revision: 317811
URL: https://svnweb.freebsd.org/changeset/base/317811

Log:
  Fix triple-finger taps reported as double-finger for Elan hw v.4 touchpads
  
  Wait for all advertised head packets after status packet have been received.
  This fixes rare but quite annoying issue in Elan hw v.4 touchpads support
  when triple-finger taps are reported as double-finger taps under several
  circumstances.
  
  Reviewed by:	gonzo
  Approved by:	gonzo (mentor)
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D10266

Modified:
  head/sys/dev/atkbdc/psm.c

Modified: head/sys/dev/atkbdc/psm.c
==============================================================================
--- head/sys/dev/atkbdc/psm.c	Thu May  4 21:40:16 2017	(r317810)
+++ head/sys/dev/atkbdc/psm.c	Thu May  4 22:47:18 2017	(r317811)
@@ -366,6 +366,7 @@ enum {
 typedef struct elantechaction {
 	finger_t		fingers[ELANTECH_MAX_FINGERS];
 	int			mask;
+	int			mask_v4wait;
 } elantechaction_t;
 
 /* driver control block */
@@ -3879,9 +3880,15 @@ proc_elantech(struct psm_softc *sc, pack
 		mask = pb->ipacket[1] & 0x1f;
 		nfingers = bitcount(mask);
 
+		if (sc->elanaction.mask_v4wait != 0)
+			VLOG(3, (LOG_DEBUG, "elantech: HW v4 status packet"
+			    " when not all previous head packets received\n"));
+
+		/* Bitmap of fingers to receive before gesture processing */
+		sc->elanaction.mask_v4wait = mask & ~sc->elanaction.mask;
+
 		/* Skip "new finger is on touchpad" packets */
-		if ((sc->elanaction.mask & mask) == sc->elanaction.mask &&
-		    (mask & ~sc->elanaction.mask)) {
+		if (sc->elanaction.mask_v4wait) {
 			sc->elanaction.mask = mask;
 			return (0);
 		}
@@ -3906,11 +3913,33 @@ proc_elantech(struct psm_softc *sc, pack
 		mask = sc->elanaction.mask;
 		nfingers = bitcount(mask);
 		id = ((pb->ipacket[3] & 0xe0) >> 5) - 1;
+		fn = ELANTECH_FINGER_SET_XYP(pb);
+		fn.w =(pb->ipacket[0] & 0xf0) >> 4;
 
-		if (id >= 0 && id < ELANTECH_MAX_FINGERS) {
-			f[id] = ELANTECH_FINGER_SET_XYP(pb);
-			f[id].w = (pb->ipacket[0] & 0xf0) >> 4;
+		if (id < 0)
+			return (0);
+
+		/* Packet is finger position update. Report it */
+		if (sc->elanaction.mask_v4wait == 0) {
+			if (id < ELANTECH_MAX_FINGERS)
+				f[id] = fn;
+			break;
 		}
+
+		/* Remove finger from waiting bitmap and store into context */
+		sc->elanaction.mask_v4wait &= ~(1 << id);
+		if (id < ELANTECH_MAX_FINGERS)
+			sc->elanaction.fingers[id] = fn;
+
+		/* Wait for other fingers if needed */
+		if (sc->elanaction.mask_v4wait != 0)
+			return (0);
+
+		/* All new fingers are received. Report them from context */
+		for (id = 0; id < ELANTECH_MAX_FINGERS; id++)
+			if (sc->elanaction.mask & (1 << id))
+				f[id] =  sc->elanaction.fingers[id];
+
 		break;
 
 	case ELANTECH_PKT_V4_MOTION:	/* HW Version 4. Motion packet */


More information about the svn-src-all mailing list