From: Tai-hwa Liang <avatar@sentelic.com>
To: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: linux-input@vger.kernel.org
Subject: [PATCH] Input: sentelic - filtering out erratic movement
Date: Fri, 6 Jul 2012 13:49:29 +0800 [thread overview]
Message-ID: <1341553769-30324-1-git-send-email-avatar@sentelic.com> (raw)
It turns out that certain hardware sometime generates unexpected movement
during normal operation. This patch tries to filter out these erratic
movements which will cause unexpected cursor jumping to the top-left corner.
This patch also tries to fix jumpy(back and forth) scrolling in X11 by
accumulating both fingers' coordinates before reporting to the input-mt layer.
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=43197
Reported-and-tested-by: Aleksey Spiridonov <leks13@leks13.ru>
Tested-by: Eddie Dunn <eddie.dunn@gmail.com>
Tested-by: Olivier Goffart <olivier@woboq.com>
---
drivers/input/mouse/sentelic.c | 114 ++++++++++++++++++++++++++--------------
drivers/input/mouse/sentelic.h | 35 ++++++++++++
2 files changed, 110 insertions(+), 39 deletions(-)
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c
index 3f5649f..995b395 100644
--- a/drivers/input/mouse/sentelic.c
+++ b/drivers/input/mouse/sentelic.c
@@ -707,7 +707,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
struct fsp_data *ad = psmouse->private;
unsigned char *packet = psmouse->packet;
unsigned char button_status = 0, lscroll = 0, rscroll = 0;
- unsigned short abs_x, abs_y, fgrs = 0;
+ unsigned short abs_x, abs_y, fgrs;
int rel_x, rel_y;
if (psmouse->pktcnt < 4)
@@ -721,64 +721,100 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
case FSP_PKT_TYPE_ABS:
+ if ((packet[0] == 0x48 || packet[0] == 0x49) &&
+ packet[1] == 0 && packet[2] == 0) {
+ /*
+ * filtering out erratic movement which will cause
+ * unexpected cursor jumping to the top-left corner
+ */
+ packet[3] &= 0xf0;
+ }
abs_x = GET_ABS_X(packet);
abs_y = GET_ABS_Y(packet);
- if (packet[0] & FSP_PB0_MFMC) {
+ if (!IS_MFMC(packet[0]) && (packet[0] & (FSP_PB0_LBTN |
+ FSP_PB0_PHY_BTN)) == FSP_PB0_LBTN) {
/*
- * MFMC packet: assume that there are two fingers on
- * pad
+ * On-pad click in SFAC mode should be handled
+ * by userspace. On-pad clicks in MFMC mode
+ * are real clickpad clicks, and not ignored.
*/
- fgrs = 2;
+ packet[0] &= ~FSP_PB0_LBTN;
+ }
+ if (abs_x == 0 || abs_y == 0) {
+ /*
+ * workaround for buggy firmware which sends zero
+ * coordinates even if there is finger on pad
+ */
+ if (!IS_MFMC(packet[0])) {
+ /* don't report bad movement */
+ fgrs = 0;
+ } else {
+ /*
+ * ignore finger up event for multiple finger
+ * scenario
+ */
+ return PSMOUSE_FULL_PACKET;
+ }
+ } else {
+ /* finger(s) down */
+ if (!IS_MFMC(packet[0])) {
+ /* SFAC, MFMC CPB packet */
+ fgrs = 1;
- /* MFMC packet */
- if (packet[0] & FSP_PB0_MFMC_FGR2) {
- /* 2nd finger */
- if (ad->last_mt_fgr == 2) {
+ /* no multi-finger information */
+ ad->last_mt_fgr = 0;
+
+ fsp_set_slot(dev, 0, true, abs_x, abs_y);
+ fsp_set_slot(dev, 1, false, 0, 0);
+ } else if (IS_MFMC_FGR1(packet[0])) {
+ /* MFMC 1st finger */
+ if (ad->last_mt_fgr == 1) {
/*
* workaround for buggy firmware
* which doesn't clear MFMC bit if
- * the 1st finger is up
+ * the 2nd finger is up
*/
fgrs = 1;
- fsp_set_slot(dev, 0, false, 0, 0);
- }
- ad->last_mt_fgr = 2;
+ fsp_set_slot(dev, 0, true,
+ abs_x, abs_y);
+ fsp_set_slot(dev, 1, false, 0, 0);
+ } else {
+ fgrs = 2;
+ ad->last_mt_fgr = 1;
- fsp_set_slot(dev, 1, fgrs == 2, abs_x, abs_y);
+ /*
+ * accumulate the coordaintes and
+ * proceed to the next run
+ */
+ ad->mfmc_x1 = abs_x;
+ ad->mfmc_y1 = abs_y;
+ }
} else {
- /* 1st finger */
- if (ad->last_mt_fgr == 1) {
+ /* MFMC 2nd finger */
+ if (ad->last_mt_fgr == 2) {
/*
* workaround for buggy firmware
* which doesn't clear MFMC bit if
- * the 2nd finger is up
+ * the 1st finger is up
*/
fgrs = 1;
- fsp_set_slot(dev, 1, false, 0, 0);
+ fsp_set_slot(dev, 0, false, 0, 0);
+ fsp_set_slot(dev, 1, true,
+ abs_x, abs_y);
+ } else {
+ fgrs = 2;
+ ad->last_mt_fgr = 2;
+
+ /* report both fingers' coordinate */
+ fsp_set_slot(dev, 1, true,
+ abs_x, abs_y);
+ abs_x = ad->mfmc_x1;
+ abs_y = ad->mfmc_y1;
+ fsp_set_slot(dev, 0, true,
+ abs_x, abs_y);
}
- ad->last_mt_fgr = 1;
- fsp_set_slot(dev, 0, fgrs != 0, abs_x, abs_y);
- }
- } else {
- /* SFAC packet */
- if ((packet[0] & (FSP_PB0_LBTN|FSP_PB0_PHY_BTN)) ==
- FSP_PB0_LBTN) {
- /* On-pad click in SFAC mode should be handled
- * by userspace. On-pad clicks in MFMC mode
- * are real clickpad clicks, and not ignored.
- */
- packet[0] &= ~FSP_PB0_LBTN;
}
-
- /* no multi-finger information */
- ad->last_mt_fgr = 0;
-
- if (abs_x != 0 && abs_y != 0)
- fgrs = 1;
-
- fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y);
- fsp_set_slot(dev, 1, false, 0, 0);
}
if (fgrs > 0) {
input_report_abs(dev, ABS_X, abs_x);
diff --git a/drivers/input/mouse/sentelic.h b/drivers/input/mouse/sentelic.h
index aa697ec..0173fc5 100644
--- a/drivers/input/mouse/sentelic.h
+++ b/drivers/input/mouse/sentelic.h
@@ -90,6 +90,39 @@
#define FSP_PB0_MUST_SET BIT(3)
#define FSP_PB0_PHY_BTN BIT(4)
#define FSP_PB0_MFMC BIT(5)
+/* packet type. See FSP_PKT_TYPE_XXX */
+#define FSP_PB0_TYPE (BIT(7) | BIT(6))
+#define FSP_PB0_TYPE_REL (0)
+#define FSP_PB0_TYPE_ABS BIT(6)
+#define FSP_PB0_TYPE_NOTIFY BIT(7)
+#define FSP_PB0_TYPE_CUSTOM (BIT(7) | BIT(6))
+
+/*
+ * physical clickpad button = MFMC packet without physical button.
+ */
+#define IS_PHY_CPB(_pb0_) \
+ (((_pb0_) & (FSP_PB0_TYPE | FSP_PB0_MFMC | FSP_PB0_PHY_BTN)) == \
+ (FSP_PB0_TYPE_ABS | FSP_PB0_MFMC))
+/*
+ * single-finger absolute coordinate
+ */
+#define IS_SFAC(_pb0_) \
+ (((_pb0_) & (FSP_PB0_TYPE | FSP_PB0_MFMC)) == FSP_PB0_TYPE_ABS)
+/*
+ * multi-finger multi-coordinate (physical clickpad button is excluded)
+ */
+#define IS_MFMC(_pb0_) \
+ (((_pb0_) & (FSP_PB0_TYPE | FSP_PB0_MFMC | FSP_PB0_PHY_BTN)) == \
+ (FSP_PB0_TYPE_ABS | FSP_PB0_MFMC | FSP_PB0_PHY_BTN))
+#define IS_MFMC_FGR1(_pb0_) \
+ (((_pb0_) & (FSP_PB0_TYPE | FSP_PB0_MFMC | FSP_PB0_PHY_BTN | \
+ FSP_PB0_MFMC_FGR2)) == (FSP_PB0_TYPE_ABS | \
+ FSP_PB0_MFMC | FSP_PB0_PHY_BTN))
+#define IS_MFMC_FGR2(_pb0_) \
+ (((_pb0_) & (FSP_PB0_TYPE | FSP_PB0_MFMC | FSP_PB0_PHY_BTN | \
+ FSP_PB0_MFMC_FGR2)) == (FSP_PB0_TYPE_ABS | \
+ FSP_PB0_MFMC | FSP_PB0_PHY_BTN | FSP_PB0_MFMC_FGR2))
+
/* hardware revisions */
#define FSP_VER_STL3888_A4 (0xC1)
@@ -117,6 +150,8 @@ struct fsp_data {
unsigned char last_reg; /* Last register we requested read from */
unsigned char last_val;
unsigned int last_mt_fgr; /* Last seen finger(multitouch) */
+ unsigned short mfmc_x1; /* X coordinate for the 1st finger */
+ unsigned short mfmc_y1; /* Y coordinate for the 1st finger */
};
#ifdef CONFIG_MOUSE_PS2_SENTELIC
--
1.7.9.5
next reply other threads:[~2012-07-06 5:49 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-06 5:49 Tai-hwa Liang [this message]
2012-07-08 0:30 ` [PATCH] Input: sentelic - filtering out erratic movement Tai-hwa Liang
2012-07-25 7:08 ` Dmitry Torokhov
2012-07-25 10:22 ` Tai-hwa Liang
-- strict thread matches above, loose matches on Subject: below --
2012-06-02 14:23 Tai-hwa Liang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1341553769-30324-1-git-send-email-avatar@sentelic.com \
--to=avatar@sentelic.com \
--cc=dmitry.torokhov@gmail.com \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).