[PATCH driver/input/synaptics] For serial devices try reconnecting if device is wedged.
Mark Kettenis
mark.kettenis at xs4all.nl
Mon Jul 29 04:31:48 PDT 2013
> From: Egbert Eich <eich at freedesktop.org>
> Date: Mon, 29 Jul 2013 13:15:13 +0200
>
> From: Takashi Iwai <tiwai at suse.de>
>
> Under some circumstances the synaptics device may be wedged when
> coming back from a sleep state. Add some magic which tries to
> detect this and reconnect.
You shouldn't use function names that start with an underscore.
> Signed-off-by: Takashi Iwai <tiwai at suse.de>
> Signed-off-by: Egbert Eich <eich at freedesktop.org>
> ---
> src/eventcomm.c | 3 ++-
> src/synaptics.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++-------
> src/synapticsstr.h | 3 +++
> 3 files changed, 54 insertions(+), 8 deletions(-)
>
> diff --git a/src/eventcomm.c b/src/eventcomm.c
> index 258a538..86b74cb 100644
> --- a/src/eventcomm.c
> +++ b/src/eventcomm.c
> @@ -638,7 +638,8 @@ EventReadHwState(InputInfoPtr pInfo,
> }
>
> while (SynapticsReadEvent(pInfo, &ev)) {
> - switch (ev.type) {
> + priv->comm_read++;
> + switch (ev.type) {
> case EV_SYN:
> switch (ev.code) {
> case SYN_REPORT:
> diff --git a/src/synaptics.c b/src/synaptics.c
> index f0a8269..31e147c 100644
> --- a/src/synaptics.c
> +++ b/src/synaptics.c
> @@ -920,18 +920,30 @@ DeviceControl(DeviceIntPtr dev, int mode)
> }
>
> static int
> -DeviceOn(DeviceIntPtr dev)
> +_DeviceOn(InputInfoPtr pInfo)
> {
> - InputInfoPtr pInfo = dev->public.devicePrivate;
> SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
> + int n;
>
> DBG(3, "Synaptics DeviceOn called\n");
>
> - pInfo->fd = xf86OpenSerial(pInfo->options);
> + for (n = priv->retries; n >= 0; n--) {
> + pInfo->fd = xf86OpenSerial(pInfo->options);
> + if (pInfo->fd != -1)
> + break;
> + if (n)
> + xf86Msg(X_WARNING, "%s: cannot open input device - "
> + "retrying %d more times\n", pInfo->name, n);
> + }
> if (pInfo->fd == -1) {
> xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n");
> return !Success;
> }
> + /* This has succeeded once, so chances are the hardware *really* is present
> + * - this is not a hotplug device after all.
> + * Without trying really hard on some machines with some kernels the device
> + * won't be found after S3/S4 again. */
> + priv->retries = 4;
>
> if (priv->proto_ops->DeviceOnHook &&
> !priv->proto_ops->DeviceOnHook(pInfo, &priv->synpara))
> @@ -956,11 +968,21 @@ DeviceOn(DeviceIntPtr dev)
> }
>
> xf86AddEnabledDevice(pInfo);
> - dev->public.on = TRUE;
>
> return Success;
> }
>
> +static int
> +DeviceOn(DeviceIntPtr dev)
> +{
> + int ret = _DeviceOn(dev->public.devicePrivate);
> +
> + if (ret == Success)
> + dev->public.on = TRUE;
> +
> + return ret;
> +}
> +
> static void
> SynapticsReset(SynapticsPrivate * priv)
> {
> @@ -995,9 +1017,8 @@ SynapticsReset(SynapticsPrivate * priv)
> }
>
> static int
> -DeviceOff(DeviceIntPtr dev)
> +_DeviceOff(InputInfoPtr pInfo)
> {
> - InputInfoPtr pInfo = dev->public.devicePrivate;
> SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
> Bool rc = Success;
>
> @@ -1018,11 +1039,18 @@ DeviceOff(DeviceIntPtr dev)
> xf86CloseSerial(pInfo->fd);
> pInfo->fd = -1;
> }
> - dev->public.on = FALSE;
> return rc;
> }
>
> static int
> +DeviceOff(DeviceIntPtr dev)
> +{
> + int ret = _DeviceOff(dev->public.devicePrivate);
> + dev->public.on = FALSE;
> + return ret;
> +}
> +
> +static int
> DeviceClose(DeviceIntPtr dev)
> {
> Bool RetValue;
> @@ -1469,6 +1497,7 @@ ReadInput(InputInfoPtr pInfo)
>
> SynapticsResetTouchHwState(hw, FALSE);
>
> + priv->comm_read = 0;
> while (SynapticsGetHwState(pInfo, priv, hw)) {
> /* Semi-mt device touch slots do not track touches. When there is a
> * change in the number of touches, we must disregard the temporary
> @@ -1487,6 +1516,19 @@ ReadInput(InputInfoPtr pInfo)
> newDelay = TRUE;
> }
>
> + if (!priv->comm_read) {
> + /* strange callback, check the device and reconnect if needed */
> + if (!priv->reconnecting) {
> + priv->reconnecting = 1;
> + xf86Msg(X_WARNING, "%s: reconnecting device...\n", pInfo->name);
> + _DeviceOff(pInfo);
> + usleep(100*1000);
> + _DeviceOn(pInfo);
> + xf86Msg(X_WARNING, "%s: reconnection done\n", pInfo->name);
> + } else
> + priv->reconnecting = 0;
> + }
> +
> if (newDelay) {
> priv->timer_time = GetTimeInMillis();
> priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
> diff --git a/src/synapticsstr.h b/src/synapticsstr.h
> index 428befa..98d6552 100644
> --- a/src/synapticsstr.h
> +++ b/src/synapticsstr.h
> @@ -204,6 +204,9 @@ struct _SynapticsPrivateRec {
> OsTimerPtr timer; /* for tap processing, etc */
>
> struct CommData comm;
> + int comm_read; /* for reconnection check */
> + int reconnecting; /* for reconnection check */
> + int retries;
>
> struct SynapticsHwState *local_hw_state; /* used in place of local hw state variables */
>
> --
> 1.8.1.4
>
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
>
More information about the xorg-devel
mailing list