On 15/08/15(Sat) 01:32, Ulf Brosziewski wrote:
> 
> The tap-and-drag gesture doesn't work reliably with the ALPS touchpads
> supported by pms. To make it work, it is necessary to start dragging
> immediately with the second touch, which doesn't always succeed.
> Increasing the tap timeout helps, but doesn't change the principle. The
> patch below solves that problem. Tests and comments would be welcome.
> 
> In case someone is interested in the background: I have observed the
> same problem with a Linux installation on a machine with an ALPS
> touchpad; however, increasing the tap timeout to a sufficiently high
> value (>= 260ms) makes it work normally. The somewhat special behaviour
> of those ALPS models is described in this LKML posting:
>     https://lkml.org/lkml/2004/7/28/210
> The approach put forward there - which is partially reproduced in the
> current version of pms - is improved by the patch as follows: When the
> hardware signals a tap, the handler does nothing. The missing events
> will be emulated when the next packet arrives, which either signals the
> end of the gesture, or the start of a drag action. No timeout will occur
> even if the hardware introduces a long delay between the first and the
> second packet (which just happens when the finger is resting after the
> second contact).

This looks good to me.

Did you get reports from other ALPS users?

> Index: dev/pckbc/pms.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pckbc/pms.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 pms.c
> --- dev/pckbc/pms.c   20 Jul 2015 00:55:06 -0000      1.64
> +++ dev/pckbc/pms.c   14 Aug 2015 18:27:57 -0000
> @@ -120,7 +120,8 @@ struct alps_softc {
> 
>       int min_x, min_y;
>       int max_x, max_y;
> -     int old_fin;
> +
> +     u_int gesture;
> 
>       u_int sec_buttons;      /* trackpoint */
> 
> @@ -1521,8 +1522,7 @@ pms_proc_alps(struct pms_softc *sc)
>  {
>       struct alps_softc *alps = sc->alps;
>       int x, y, z, w, dx, dy;
> -     u_int buttons;
> -     int fin, ges;
> +     u_int buttons, gesture;
> 
>       if ((alps->model & ALPS_DUALPOINT) && alps_sec_proc(sc))
>               return;
> @@ -1557,28 +1557,44 @@ pms_proc_alps(struct pms_softc *sc)
>       y = ALPS_YMAX_BEZEL - y + ALPS_YMIN_BEZEL;
> 
>       if (alps->wsmode == WSMOUSE_NATIVE) {
> -             ges = sc->packet[2] & 0x01;
> -             fin = sc->packet[2] & 0x02;
> +             if (alps->gesture == ALPS_TAP) {
> +                     /* Report a touch with the tap coordinates. */
> +                     wsmouse_input(sc->sc_wsmousedev, buttons,
> +                         alps->old_x, alps->old_y, ALPS_PRESSURE, 4,
> +                         WSMOUSE_INPUT_ABSOLUTE_X
> +                         | WSMOUSE_INPUT_ABSOLUTE_Y
> +                         | WSMOUSE_INPUT_ABSOLUTE_Z
> +                         | WSMOUSE_INPUT_ABSOLUTE_W);
> +                     if (z > 0) {
> +                             /*
> +                              * The hardware doesn't send a null pressure
> +                              * event when dragging starts.
> +                              */
> +                             wsmouse_input(sc->sc_wsmousedev, buttons,
> +                                 alps->old_x, alps->old_y, 0, 0,
> +                                 WSMOUSE_INPUT_ABSOLUTE_X
> +                                 | WSMOUSE_INPUT_ABSOLUTE_Y
> +                                 | WSMOUSE_INPUT_ABSOLUTE_Z
> +                                 | WSMOUSE_INPUT_ABSOLUTE_W);
> +                     }
> +             }
> 
> -             /* Simulate click (tap) */
> -             if (ges && !fin)
> -                     z = 35;
> -
> -             /* Generate a null pressure event (needed for tap & drag) */
> -             if (ges && fin && !alps->old_fin)
> -                     z = 0;
> -
> -             /* Generate a width value corresponding to one finger */
> -             if (z > 0)
> -                     w = 4;
> -             else
> -                     w = 0;
> +             gesture = sc->packet[2] & 0x03;
> +             if (gesture != ALPS_TAP) {
> +                     w = z ? 4 : 0;
> +                     wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
> +                         WSMOUSE_INPUT_ABSOLUTE_X
> +                         | WSMOUSE_INPUT_ABSOLUTE_Y
> +                         | WSMOUSE_INPUT_ABSOLUTE_Z
> +                         | WSMOUSE_INPUT_ABSOLUTE_W);
> +             }
> 
> -             wsmouse_input(sc->sc_wsmousedev, buttons, x, y, z, w,
> -                 WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y |
> -                 WSMOUSE_INPUT_ABSOLUTE_Z | WSMOUSE_INPUT_ABSOLUTE_W);
> +             if (alps->gesture != ALPS_DRAG || gesture != ALPS_TAP)
> +                     alps->gesture = gesture;
> +
> +             alps->old_x = x;
> +             alps->old_y = y;
> 
> -             alps->old_fin = fin;
>       } else {
>               dx = dy = 0;
>               if (z > ALPS_PRESSURE) {
> Index: dev/pckbc/pmsreg.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/pckbc/pmsreg.h,v
> retrieving revision 1.11
> diff -u -p -r1.11 pmsreg.h
> --- dev/pckbc/pmsreg.h        26 Mar 2015 01:30:22 -0000      1.11
> +++ dev/pckbc/pmsreg.h        14 Aug 2015 18:27:57 -0000
> @@ -164,6 +164,10 @@
> 
>  #define ALPS_Z_MAGIC                         127
> 
> +/* ALPS "gesture" and "finger" bits */
> +#define ALPS_TAP                             0x01
> +#define ALPS_DRAG                            0x03
> +
>  /* Elantech queries */
>  #define ELANTECH_QUE_FW_ID                   0
>  #define ELANTECH_QUE_FW_VER                  1
> 

Reply via email to