From patchwork Sat Oct 2 20:42:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Drake X-Patchwork-Id: 227241 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o92KrIFF009646 for ; Sat, 2 Oct 2010 20:53:19 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751794Ab0JBUxS (ORCPT ); Sat, 2 Oct 2010 16:53:18 -0400 Received: from queueout04-winn.ispmail.ntl.com ([81.103.221.58]:3704 "EHLO queueout04-winn.ispmail.ntl.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751689Ab0JBUxS (ORCPT ); Sat, 2 Oct 2010 16:53:18 -0400 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Sat, 02 Oct 2010 20:53:19 +0000 (UTC) X-Greylist: delayed 636 seconds by postgrey-1.27 at vger.kernel.org; Sat, 02 Oct 2010 16:53:15 EDT Received: from aamtaout03-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout02-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20101002204242.MKWW3192.mtaout02-winn.ispmail.ntl.com@aamtaout03-winn.ispmail.ntl.com>; Sat, 2 Oct 2010 21:42:42 +0100 Received: from zog.reactivated.net ([86.14.215.141]) by aamtaout03-winn.ispmail.ntl.com (InterMail vG.2.02.00.01 201-2161-120-102-20060912) with ESMTP id <20101002204242.OCHC1807.aamtaout03-winn.ispmail.ntl.com@zog.reactivated.net>; Sat, 2 Oct 2010 21:42:42 +0100 Received: by zog.reactivated.net (Postfix, from userid 1000) id CB11A9D401C; Sat, 2 Oct 2010 21:42:39 +0100 (BST) From: Daniel Drake To: dmitry.torokhov@gmail.com To: dtor@mail.ru Cc: linux-input@vger.kernel.org Cc: pgf@laptop.org Subject: [PATCH 2/3] Input: hgpk - Rework spew detection Message-Id: <20101002204239.CB11A9D401C@zog.reactivated.net> Date: Sat, 2 Oct 2010 21:42:39 +0100 (BST) X-Cloudmark-Analysis: v=1.1 cv=4QByPj+6Iq2k/6L54d+eVKTdgQxdscpRskJJReCfdXo= c=1 sm=0 a=A0WczmwTea8A:10 a=Op-mwl0xAAAA:8 a=oJ1ZDu8fv1PDBHo4Ti8A:9 a=gz1WiDozWr9-_C2iFIEA:7 a=ttZ24BBCxIpizKFCQ4A0OAF5ALgA:4 a=d4CUUju0HPYA:10 a=HpAAvcLHHh0Zw7uRqdWCyQ==:117 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index de635ed..a6c4ffe 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c @@ -58,7 +58,7 @@ module_param(jumpy_delay, int, 0644); MODULE_PARM_DESC(jumpy_delay, "delay (ms) before recal after jumpiness detected"); -static int spew_delay = 1000; +static int spew_delay = 1; module_param(spew_delay, int, 0644); MODULE_PARM_DESC(spew_delay, "delay (ms) before recal after packet spew detected"); @@ -95,6 +95,14 @@ static void hgpk_jumpy_hack(struct psmouse *psmouse, int x, int y) } } +static void reset_spew_detection(struct hgpk_data *priv) +{ + priv->spew_count = 0; + priv->x_tally = 0; + priv->y_tally = 0; + priv->spew_flag = NO_SPEW; +} + /* * We have no idea why this particular hardware bug occurs. The touchpad * will randomly start spewing packets without anything touching the @@ -120,20 +128,57 @@ static void hgpk_spewing_hack(struct psmouse *psmouse, if (l || r) return; + /* don't track spew if the workaround feature has been turned off */ + if (!spew_delay) + return; + + if (abs(x) > 3 || abs(y) > 3) { + /* no spew, or spew ended */ + reset_spew_detection(priv); + return; + } + + /* Keep a tally of the overall delta to the cursor position caused by + * the spew */ priv->x_tally += x; priv->y_tally += y; - if (++priv->count > 100) { + switch (priv->spew_flag) { + case NO_SPEW: + /* we're not spewing, but this packet might be the start */ + priv->spew_flag = MAYBE_SPEWING; + + /* fall-through */ + + case MAYBE_SPEWING: + priv->spew_count++; + + if (priv->spew_count < SPEW_WATCH_COUNT) + break; + + /* excessive spew detected, request recalibration */ + priv->spew_flag = SPEW_DETECTED; + + /* fall-through */ + + case SPEW_DETECTED: + /* only recalibrate when the overall delta to the cursor + * is really small. if the spew is causing significant cursor + * movement, it is probably a case of the user moving the + * cursor very slowly across the screen. */ if (abs(priv->x_tally) < 3 && abs(priv->y_tally) < 3) { - hgpk_dbg(psmouse, "packet spew detected (%d,%d)\n", + hgpk_err(psmouse, "packet spew detected (%d,%d)\n", priv->x_tally, priv->y_tally); + priv->spew_flag = RECALIBRATING; psmouse_queue_work(psmouse, &priv->recalib_wq, msecs_to_jiffies(spew_delay)); } - /* reset every 100 packets */ - priv->count = 0; - priv->x_tally = 0; - priv->y_tally = 0; + + break; + case RECALIBRATING: + /* we already detected a spew and requested a recalibration, + * just wait for the queue to kick into action. */ + break; } } @@ -229,9 +274,18 @@ static int process_advanced_packet(struct psmouse *psmouse, int *x, int *y, * relative calcs, and our jump detection. */ if (*x == priv->abs_x && *y == priv->abs_y) { + if (++priv->dupe_count > SPEW_WATCH_COUNT) { + if (tpdebug) + hgpk_dbg(psmouse, "hard spew detected\n"); + priv->spew_flag = RECALIBRATING; + psmouse_queue_work(psmouse, &priv->recalib_wq, + msecs_to_jiffies(spew_delay)); + } if (tpdebug) hgpk_dbg(psmouse, "dupe\n"); return -1; + } else { + priv->dupe_count = 0; } /* @@ -378,6 +432,7 @@ static int hgpk_force_recalibrate(struct psmouse *psmouse) msleep(150); priv->isdown = false; + reset_spew_detection(priv); if (hgpk_advanced_mode(psmouse)) { hgpk_err(psmouse, "Failed to reinit advanced mode!\n"); diff --git a/drivers/input/mouse/hgpk.h b/drivers/input/mouse/hgpk.h index 002df7b..1ec18c8 100644 --- a/drivers/input/mouse/hgpk.h +++ b/drivers/input/mouse/hgpk.h @@ -16,12 +16,23 @@ enum hgpk_model_t { HGPK_MODEL_D = 0x50, /* C1, mass production */ }; +enum hgpk_spew_flag { + NO_SPEW, + MAYBE_SPEWING, + SPEW_DETECTED, + RECALIBRATING, +}; + +#define SPEW_WATCH_COUNT 42 /* at 12ms/packet, this is 1/2 second */ + struct hgpk_data { struct psmouse *psmouse; bool powered; bool isdown; - int count, x_tally, y_tally; /* hardware workaround stuff */ + enum hgpk_spew_flag spew_flag; + int spew_count, x_tally, y_tally; /* spew detection */ int abs_x, abs_y; /* for computing delta in advanced mode */ + int dupe_count; int buttons; unsigned long recalib_window; struct delayed_work recalib_wq;