From patchwork Sun Aug 1 11:28:04 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4PigLByaWMgUGllbA==?= X-Patchwork-Id: 116302 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o71BS9BX025754 for ; Sun, 1 Aug 2010 11:28:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752188Ab0HAL2D (ORCPT ); Sun, 1 Aug 2010 07:28:03 -0400 Received: from mailservice.tudelft.nl ([130.161.131.5]:35776 "EHLO mailservice.tudelft.nl" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751921Ab0HAL2B (ORCPT ); Sun, 1 Aug 2010 07:28:01 -0400 Received: from localhost (localhost [127.0.0.1]) by amavis (Postfix) with ESMTP id 2DD707F8150; Sun, 1 Aug 2010 13:28:00 +0200 (CEST) X-Virus-Scanned: amavisd-new at tudelft.nl X-Spam-Flag: NO X-Spam-Score: -22.589 X-Spam-Level: X-Spam-Status: No, score=-22.589 tagged_above=-99 required=5 tests=[BAYES_00=-2.599, PROLO_LEO3=0.01, TUD_REL01=-20] autolearn=ham Received: from mailservice.tudelft.nl ([130.161.131.69]) by localhost (tudelft.nl [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id TubWronQ9e7q; Sun, 1 Aug 2010 13:27:59 +0200 (CEST) Received: from smtp-a.tudelft.nl (smtp-a.tudelft.nl [130.161.180.7]) by mx1.tudelft.nl (Postfix) with ESMTP id DCAE97F8127; Sun, 1 Aug 2010 13:27:58 +0200 (CEST) Received: from [172.19.3.21] (63-103-dsl.ipact.nl [84.35.103.63]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp-a.tudelft.nl (Postfix) with ESMTP id 944FAB3A62; Sun, 1 Aug 2010 13:27:58 +0200 (CEST) Message-ID: <4C555A44.5050505@tudelft.nl> Date: Sun, 01 Aug 2010 13:28:04 +0200 From: =?ISO-8859-1?Q?=C9ric_Piel?= User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.7) Gecko/20100724 Mandriva/3.1.1-2mdv2011.0 (2011.0) Thunderbird/3.1.1 MIME-Version: 1.0 To: Henrik Rydberg CC: Chris Bagwell , Dmitry Torokhov , "linux-input@vger.kernel.org" , Florian Ragwitz Subject: Re: [PATCH 7/7] elantech: average the two coordinates when 2 fingers References: <4C1FD2B0.1080504@tudelft.nl> <4C1FD454.4050807@tudelft.nl> <20100721033655.GA9070@core.coreip.homeip.net> <4C532009.4020103@tudelft.nl> <4C533DC3.9070001@euromail.se> <4C54ABFE.8050106@tudelft.nl> <4C554058.6080203@euromail.se> In-Reply-To: <4C554058.6080203@euromail.se> X-Enigmail-Version: 1.1.2 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sun, 01 Aug 2010 11:28:10 +0000 (UTC) differentiate anymore when they dis-align. And I don't think using motion will help because the hardware tends to report _exactly_ the same value as soon the two fingers become close (= a segment instead of a rectangle). Or motion tracking would require a long window of past frames. I still think that for the very specific use case of scrolling when pressing one finger and moving up and dow the other one, reporting the average works better than the first finger. However, I guess this can be considered just as a drawback of the ST protocol, and fixed in userspace by using the MT protocol. What do you think? Does it look fine to you? Below is the code. Eric 8<-------------------------------------------------------------------- The elantech hardware is limited when reporting two fingers. It just reports the minimum and maximum coordinates of the rectangle containing the fingers. As multitouch protocol requires at least to report the correct position of each finger, we track the finger position when there is only one finger to distinguish which corner of the rectangle corresponds to the actual position of the fingers. When there are three fingers, only the minimum position is reported, so we just don't track it and hope the last tracked position has the most likelihood to be correct. It works fine, at least as long as the two fingers don't get horizontally or vertically aligned, after what it's back to random. This also allows to avoid so "jumps" in the single-touch protocol. Signed-off-by: Éric Piel --- drivers/input/mouse/elantech.c | 51 ++++++++++++++++++++++++++++++++-------- drivers/input/mouse/elantech.h | 2 + 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index bb66ae8..a3a3d8d 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -242,6 +242,33 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) input_sync(dev); } + +static void track_one_finger(struct elantech_data *etd, int x, int y) +{ + etd->prev_x = x; + etd->prev_y = y; +} + +static void find_closest_and_swap(int *ref, int *a, int *b) +{ + int diff_a = abs(*ref - *a); + int diff_b = abs(*ref - *b); + int tmp; + if (diff_b < diff_a) { + tmp = *a; + *a = *b; + *b = tmp; + } + *ref = *a; +} + +static void track_two_fingers(struct elantech_data *etd, int *x1, int *y1, int *x2, int *y2) +{ + find_closest_and_swap(&etd->prev_x, x1, x2); + find_closest_and_swap(&etd->prev_y, y1, y2); +} + + /* * Interpret complete data packets and report absolute mode input events for * hardware version 2. (6 byte packets) @@ -284,6 +311,8 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) input_report_abs(dev, ABS_X, x1); input_report_abs(dev, ABS_Y, y1); + if (fingers == 1) + track_one_finger(etd, x1, y1); pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); width = ((packet[0] & 0x30) >> 2) | ((packet[3] & 0x30) >> 4); @@ -296,29 +325,31 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) * byte 0: . . ay8 ax8 . . . . * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ - x1 = ((packet[0] & 0x10) << 4) | packet[1]; + x1 = (((packet[0] & 0x10) << 4) | packet[1]) << 2; /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ - y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); + y1 = (ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2])) << 2; /* * byte 3: . . by8 bx8 . . . . * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ - x2 = ((packet[3] & 0x10) << 4) | packet[4]; + x2 = (((packet[3] & 0x10) << 4) | packet[4]) << 2; /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ - y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); + y2 = (ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5])) << 2; + + track_two_fingers(etd, &x1, &y1, &x2, &y2); /* Multitouch */ - input_report_abs(dev, ABS_MT_POSITION_X, x1 << 2); - input_report_abs(dev, ABS_MT_POSITION_Y, y1 << 2); + input_report_abs(dev, ABS_MT_POSITION_X, x1); + input_report_abs(dev, ABS_MT_POSITION_Y, y1); input_mt_sync(dev); - input_report_abs(dev, ABS_MT_POSITION_X, x2 << 2); - input_report_abs(dev, ABS_MT_POSITION_Y, y2 << 2); + input_report_abs(dev, ABS_MT_POSITION_X, x2); + input_report_abs(dev, ABS_MT_POSITION_Y, y2); input_mt_sync(dev); /* * For compatibility with non-multitouch userspace apps * report the average of both coordinates and scale up. */ - input_report_abs(dev, ABS_X, (x1 + x2) << 1); - input_report_abs(dev, ABS_Y, (y1 + y2) << 1); + input_report_abs(dev, ABS_X, (x1 + x2) >> 1); + input_report_abs(dev, ABS_Y, (y1 + y2) >> 1); /* * For compatibility with the proprietary X Elantech driver * report both coordinates as hat coordinates diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index f6e3be5..fa9a6b4 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h @@ -111,6 +111,8 @@ struct elantech_data { unsigned char hw_version; unsigned int fw_version; unsigned char parity[256]; + unsigned int prev_x; + unsigned int prev_y; }; enum paritycheck_types {