If the device is turned off, usually by syndaemon to disable the touchpad while the typing, the touch state will not be updated with the latest hardware state changes. If a touch begins while the device is off and ends while the device is on, then the touch count will be decremented without any previous increment. A similar effect will occur if the device is on when the touch begins, but off when the touch ends.
If the touch count goes negative, the index into the touch slot mask array will be out of bounds. This can corrupt memory and cause random crashes. Signed-off-by: Chase Douglas <[email protected]> --- src/synaptics.c | 74 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/synaptics.c b/src/synaptics.c index 65b48ee..4784157 100644 --- a/src/synaptics.c +++ b/src/synaptics.c @@ -2596,6 +2596,42 @@ repeat_scrollbuttons(const InputInfoPtr pInfo, return delay; } +/* Update the open slots and number of active touches */ +static void +UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw) +{ +#ifdef HAVE_MULTITOUCH + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + int i; + + for (i = 0; i < hw->num_mt_mask; i++) + { + if (hw->slot_state[i] == SLOTSTATE_OPEN) + { + priv->open_slots[priv->num_active_touches] = i; + priv->num_active_touches++; + } else if (hw->slot_state[i] == SLOTSTATE_CLOSE) + { + Bool found = FALSE; + int j; + + for (j = 0; j < priv->num_active_touches - 1; j++) + { + if (priv->open_slots[j] == i) + found = TRUE; + + if (found) + priv->open_slots[j] = priv->open_slots[j + 1]; + } + + priv->num_active_touches--; + } + } + + SynapticsResetTouchHwState(hw); +#endif +} + static void HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw) { @@ -2675,40 +2711,9 @@ HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw) xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0, hw->mt_mask[slot]); } - -out: - /* Update the open slots and number of active touches */ - for (i = 0; i < hw->num_mt_mask; i++) - { - if (hw->slot_state[i] == SLOTSTATE_OPEN) - { - priv->open_slots[priv->num_active_touches] = i; - priv->num_active_touches++; - } else if (hw->slot_state[i] == SLOTSTATE_CLOSE) - { - Bool found = FALSE; - int j; - for (j = 0; j < priv->num_active_touches - 1; j++) - { - if (priv->open_slots[j] == i) - found = TRUE; - - if (found) - priv->open_slots[j] = priv->open_slots[j + 1]; - } - - priv->num_active_touches--; - } - } - - /* We calculated the value twice, might as well double check our math */ - if (priv->num_active_touches != new_active_touches) - xf86IDrvMsg(pInfo, X_WARNING, - "calculated wrong number of active touches (%d vs %d)\n", - priv->num_active_touches, new_active_touches); - - SynapticsResetTouchHwState(hw); +out: + UpdateTouchState(pInfo, hw); #endif } @@ -2741,7 +2746,10 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now, /* If touchpad is switched off, we skip the whole thing and return delay */ if (para->touchpad_off == 1) + { + UpdateTouchState(pInfo, hw); return delay; + } /* apply hysteresis before doing anything serious. This cancels * out a lot of noise which might surface in strange phenomena -- 1.7.9 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
