[PATCH synaptics] Support the new Lenovo X1 Carbon 3rd trackpoint buttons

Hans de Goede hdegoede at redhat.com
Thu Jan 29 00:50:12 PST 2015


Hi,

On 29-01-15 03:00, Peter Hutterer wrote:
> This device has the trackpoint buttons wired up to the touchpad to send BTN_0,
> BTN_1 and BTN_2 for left, right, middle. This conflicts with previous
> touchpads that used those event codes for dedicated scroll buttons.
>
> Add an option HasTrackpointButtons that can be set via a xorg.conf.d
> snippets. This option is not intended as a user-set option, rather
> we expect distributions to ship some conglomerate of udev/hal rules with
> xorg.conf snippets that take effect.
>
> If the option is set, we look at the three affected buttons at the beginning
> of HandleState and send button events immediately for them. The HW state is
> reset to neutral and other processing continues. This saves us from having to
> synchronize these buttons with software buttons (also present on this device),
> tapping, etc.
>
> Since the buttons are physically different and (mentally) associated with the
> trackpoint device we also don't need to worry about having finger motion event
> correctly synced up with the button presses - it's acceptable to send the
> presses before the motion events.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

Looks good.

Reviewed-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans

> ---
>   conf/50-synaptics.conf  |  7 +++++++
>   conf/71-synaptics.rules |  9 +++++++++
>   man/synaptics.man       | 14 ++++++++++++++
>   src/synaptics.c         | 42 ++++++++++++++++++++++++++++++++++++++++++
>   src/synapticsstr.h      |  2 ++
>   5 files changed, 74 insertions(+)
>   create mode 100644 conf/71-synaptics.rules
>
> diff --git a/conf/50-synaptics.conf b/conf/50-synaptics.conf
> index aa50456..5fb131e 100644
> --- a/conf/50-synaptics.conf
> +++ b/conf/50-synaptics.conf
> @@ -44,3 +44,10 @@ Section "InputClass"
>           MatchDriver "synaptics"
>           Option "SoftButtonAreas" "0 0 0 0 0 0 0 0"
>   EndSection
> +
> +Section "InputClass"
> +        Identifier "Lenovo *50 and Carbon 3rd trackpoint buttons"
> +        MatchDriver "synaptics"
> +        MatchTag "has_trackpoint_buttons"
> +        Option "HasTrackpointButtons" "on"
> +EndSection
> diff --git a/conf/71-synaptics.rules b/conf/71-synaptics.rules
> new file mode 100644
> index 0000000..b1cec40
> --- /dev/null
> +++ b/conf/71-synaptics.rules
> @@ -0,0 +1,9 @@
> +ACTION=="remove", GOTO="touchpad_end"
> +KERNEL!="event*", GOTO="touchpad_end"
> +ENV{ID_INPUT_TOUCHPAD}=="", GOTO="touchpad_end"
> +
> +KERNELS=="serio1", \
> +    ATTRS{firmware_id}=="*LEN0048*", \
> +    ENV{ID_INPUT.tags}="has_trackpoint_buttons"
> +
> +LABEL="touchpad_end"
> diff --git a/man/synaptics.man b/man/synaptics.man
> index 7083b3a..65fb337 100644
> --- a/man/synaptics.man
> +++ b/man/synaptics.man
> @@ -518,6 +518,20 @@ initialized if
>   .B Option \*qHasSecondarySoftButtons\*q
>   is enabled and this option is set in the __xconfigfile__(__filemansuffix__).
>   .
> +.TP
> +.BI "Option \*qHasTrackpointButtons\*q \*q" boolean \*q
> +This option is only available on selected devices. You should never need to
> +set this option manually, your distribution should ship
> +__xconfigfile__(__filemansuffix__) snippets to enable this option where
> +required. Devices that require this option include the Lenovo X1 Carbon 3rd
> +and the Lenovo *50 series (T450, T550, etc.).
> +If enabled, the device is considered to have the trackpoint left, middle,
> +right buttons wired to the touchpad. If set, this option disables scroll
> +buttons, i.e.
> +.B Option \*qUpDownScrolling\*q, \*qLeftRightScrolling\*q
> +and the respective repeat options for scroll buttons.
> +This options is considered a hardware property and is not exposed as
> +configurable X Input device property.
>
>   .SH CONFIGURATION DETAILS
>   .SS Area handling
> diff --git a/src/synaptics.c b/src/synaptics.c
> index 955b042..07b012f 100644
> --- a/src/synaptics.c
> +++ b/src/synaptics.c
> @@ -703,6 +703,12 @@ set_default_parameters(InputInfoPtr pInfo)
>       pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", TOUCHPAD_ON);
>
>       if (priv->has_scrollbuttons) {
> +        priv->has_trackpoint_buttons = xf86SetBoolOption(opts, "HasTrackpointButtons", FALSE);
> +        if (priv->has_trackpoint_buttons)
> +            priv->has_scrollbuttons = FALSE;
> +    }
> +
> +    if (priv->has_scrollbuttons) {
>           pars->updown_button_scrolling =
>               xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
>           pars->leftright_button_scrolling =
> @@ -1081,6 +1087,7 @@ SynapticsReset(SynapticsPrivate * priv)
>       priv->mid_emu_state = MBE_OFF;
>       priv->nextRepeat = 0;
>       priv->lastButtons = 0;
> +    priv->lastTrackpointButtons = 0;
>       priv->prev_z = 0;
>       priv->prevFingers = 0;
>       priv->num_active_touches = 0;
> @@ -2779,6 +2786,34 @@ handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
>       }
>   }
>
> +static void
> +handle_trackpoint_buttons(const InputInfoPtr pInfo,
> +                          struct SynapticsHwState *hw)
> +{
> +    SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
> +    unsigned int buttons, change;
> +    int id;
> +
> +   buttons = (hw->multi[0] ? 0x1 : 0) |
> +             (hw->multi[1] ? 0x4 : 0) |
> +             (hw->multi[2] ? 0x2 : 0);
> +
> +    change = buttons ^ priv->lastTrackpointButtons;
> +    while (change) {
> +        id = ffs(change);       /* number of first set bit 1..32 is returned */
> +        change &= ~(1 << (id - 1));
> +        xf86PostButtonEvent(pInfo->dev, FALSE, id,
> +                            (buttons & (1 << (id - 1))),
> +                            0, 0);
> +    }
> +
> +    hw->multi[0] = FALSE;
> +    hw->multi[1] = FALSE;
> +    hw->multi[2] = FALSE;
> +
> +    priv->lastTrackpointButtons = buttons;
> +}
> +
>   /* Adjust the hardware state according to the extra buttons (if the touchpad
>    * has any and not many touchpads do these days). These buttons are up/down
>    * tilt buttons and/or left/right buttons that then map into a specific
> @@ -3134,6 +3169,13 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
>       Bool using_cumulative_coords = FALSE;
>       Bool ignore_motion;
>
> +    /* if we have phys. trackpoint buttons wired up to the touchpad, process
> +     * them first. They belong to a different device so we don't care about
> +     * sending out motion events before the trackpoint buttons. This makes
> +     * the code a lot easier to slot in */
> +    if (priv->has_trackpoint_buttons)
> +        handle_trackpoint_buttons(pInfo, hw);
> +
>       /* We need both and x/y, the driver can't handle just one of the two
>        * yet. But since it's possible to hit a phys button on non-clickpads
>        * without ever getting motion data first, we must continue with 0/0 for
> diff --git a/src/synapticsstr.h b/src/synapticsstr.h
> index f8ab14e..91c41fc 100644
> --- a/src/synapticsstr.h
> +++ b/src/synapticsstr.h
> @@ -289,6 +289,7 @@ struct _SynapticsPrivateRec {
>       int repeatButtons;          /* buttons for repeat */
>       int nextRepeat;             /* Time when to trigger next auto repeat event */
>       int lastButtons;            /* last state of the buttons */
> +    int lastTrackpointButtons;  /* last state of the trackpoint buttons */
>       int prev_z;                 /* previous z value, for palm detection */
>       int prevFingers;            /* previous numFingers, for transition detection */
>       int avg_width;              /* weighted average of previous fingerWidth values */
> @@ -308,6 +309,7 @@ struct _SynapticsPrivateRec {
>       Bool has_pressure;          /* device reports pressure */
>       Bool has_width;             /* device reports finger width */
>       Bool has_scrollbuttons;     /* device has physical scrollbuttons */
> +    Bool has_trackpoint_buttons;/* device has trackpoint buttons wired to touchpad */
>       Bool has_semi_mt;           /* device is only semi-multitouch capable */
>       Bool has_mt_palm_detect;    /* device reports per finger width and pressure */
>
>


More information about the xorg-devel mailing list