From patchwork Sun Mar 5 23:52:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Lyons X-Patchwork-Id: 9604835 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3DBDE601D2 for ; Sun, 5 Mar 2017 23:58:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 22FFF27D5D for ; Sun, 5 Mar 2017 23:58:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0520527C0B; Sun, 5 Mar 2017 23:58:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_TVD_MIME_EPI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1DB8227C0B for ; Sun, 5 Mar 2017 23:58:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752487AbdCEX6j (ORCPT ); Sun, 5 Mar 2017 18:58:39 -0500 Received: from know-smtprelay-omc-5.server.virginmedia.net ([80.0.253.69]:35136 "EHLO know-smtprelay-omc-5.server.virginmedia.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752442AbdCEX6i (ORCPT ); Sun, 5 Mar 2017 18:58:38 -0500 X-Greylist: delayed 322 seconds by postgrey-1.27 at vger.kernel.org; Sun, 05 Mar 2017 18:58:37 EST Received: from [192.168.0.26] ([82.14.233.67]) by know-smtprelay-5-imp with bizsmtp id sPsQ1u0061TulH601PsQU9; Sun, 05 Mar 2017 23:52:25 +0000 X-Originating-IP: [82.14.233.67] X-Spam: 0 X-Authority: v=2.1 cv=CMjXJkfD c=1 sm=1 tr=0 a=6j+RQFtdn4Y64ssuWgem6w==:117 a=6j+RQFtdn4Y64ssuWgem6w==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=_3N2Z0r8BO4A:10 a=13zjGPudsaEWiJwPRgMA:9 a=WbPmnYzAfxEA:10 a=r77TgQKjGQsHNAKrUKIA:9 a=D19gQVrFAAAA:8 a=2v9JOHaCAAAA:8 a=NcN59idvAAAA:8 a=EI8hIjTsEG0MNRmXTo4A:9 a=QEXdDO2ut3YA:10 a=WPST3_4X5qsA:10 a=ROMksOkImG8v6htBzroA:9 a=grguIe-EMD2udDcD6d8A:9 a=W4TVW4IDbPiebHqcZpNg:22 a=abvChAuvvMSDYDnsOeuN:22 a=Knr_CIXalUw3siAsRAOk:22 To: linux-input@vger.kernel.org From: Stephen Lyons Subject: [patch] input: psmouse - fix for second scroll wheel on A4Tech Dual-Scroll wheel mice Message-ID: Date: Sun, 5 Mar 2017 23:52:11 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.6.0 MIME-Version: 1.0 Sender: linux-input-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This Far-Eastern company's PS/2 mice use a deviant format for the data relating to movement of the scroll wheels for, at least, their dual wheel mice, such as their "Optical GreatEye Wheelmouse" model "WOP-35". This product has five "buttons" (one of which is the click action on the first wheel) and TWO scroll wheels. However for a byte comprising d0-d7 instead of setting one of d6-7 in the forth byte of the mouse data packet and a twos complement number of scroll steps in the remaining d5-d0 (or d3-d0 should there be a fourth (BTN_SIDE - d4) or fifth (BTN_EXTRA - d5) button to report; they only report a single +/- event for each wheel and use a bit pattern that corresponds to +/-1 for the first wheel and +/- 2 for the second in the lower nibble of the fourth byte. The effect with existing code is that the second mouse wheel merely repeats the effect of the first but providing two steps per click rather than the one of the first wheel - so there is no HORIZONTAL scroll wheel movement detected from the device as far as the rest of the kernel sees it. This patch, if enabled by the "a4tech_workaround" module parameter modifies the handling just for mice of type PSMOUSE_IMEX so that the second scroll wheel movement gets correctly reported as REL_HWHEEL events. Should this module parameter be activated for other mice of the same PSMOUSE_IMEX type then it is possible that at the point where the mouse reports more than a single movement step the user may start seeing horizontal rather than vertical wheel events, but should the movement steps get to be more than two at a time the hack will get immediately deactivated and the behaviour will revert to the past code. This was discussed around fifteen years ago on the LKML and the best summary is in post https://lkml.org/lkml/2002/7/18/111 "Re: PS2 Input Core Support" by Vojtech Pavlik. I was not able to locate any discussion later than this on this topic. Given that most users of the "psmouse" module will NOT want this additional feature enabled I have taken the apparently erroneous step of defaulting the module parameter that enables it to be "disabled" - this functionality may interfere with the operation of "normal" mice of this type (until a large enough scroll wheel movement is detected) so I cannot see how it would want to be enabled for "normal" users - i.e. everyone without this brand of mouse. I am using this patch at the moment and I can confirm that it is working for me as both a module and compiled into the kernel for my mouse that is of the type (WOP-35) described - I note that it is still available from certain on-line retailers and that the manufacturers site does not list GNU/Linux as being supported on the product page - this patch enables full use of this product: http://www.a4tech.com/product.asp?cid=1&scid=8&id=22 Tested-by: Stephen Lyons Signed-off-by: Stephen Lyons diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index a598b72..cb3d68a 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c @@ -68,6 +68,10 @@ static bool psmouse_smartscroll = true; module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); +static bool psmouse_a4tech_2wheels = false; +module_param_named(a4tech_workaround, psmouse_a4tech_2wheels, bool, 0644); +MODULE_PARM_DESC(a4tech_workaround, "A4Tech second scroll wheel workaround, 1 = enabled, 0 = disabled(default)."); + static unsigned int psmouse_resetafter = 5; module_param_named(resetafter, psmouse_resetafter, uint, 0644); MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); @@ -164,13 +168,64 @@ psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse) input_report_rel(dev, REL_HWHEEL, (int) (packet[3] & 32) - (int) (packet[3] & 31)); break; case 0x00: - case 0xC0: - input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 8) - (int) (packet[3] & 7)); + case 0xC0: /* + * Some A4Tech mice have two scroll wheels but they + * only return +/-1 for first or +/-2 for second + * scroll wheel using LS Nibble so standard code + * effectively multipled the movement by two for the + * second wheel but reported it as a first wheel + * movement. + */ + if (psmouse_a4tech_2wheels) + switch (packet[3] & 0x0F) { + case 0x0F: /* Upwards on first wheel*/ + input_report_rel(dev, REL_WHEEL, + (int) (+1)); + break; + case 0x0E: /* + * Upwards on second wheel, sign + * inverted so it becomes to the left + */ + input_report_rel(dev, REL_HWHEEL, + (int) (-1)); + break; + case 0x02: /* + * Downwards on second wheel, sign + * inverted so it becomes to the + * right + */ + input_report_rel(dev, REL_HWHEEL, + (int) (+1)); + break; + case 0x01: /* Downwards on first wheel */ + input_report_rel(dev, REL_WHEEL, + (int) (-1)); + break; + case 0x00: /* Valid, but no-op */ + break; + default: /* + * Out of range data, assume hack is not + * applicable after all. + */ + psmouse_warn(psmouse, + "%s at %s - unexpected scroll wheel data detected!\n" + "Bytes processed were: 0x%02x%02x%02x%02x.\n" + "The A4Tech Second scroll wheel workaround has been disabled.\n", + psmouse->name, psmouse->phys, + packet[0], packet[1], + packet[2], packet[3]); + psmouse_a4tech_2wheels = false; + } + else + input_report_rel(dev, REL_WHEEL, + (int) (packet[3] & 8) + -(int) (packet[3] & 7)); + input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1); input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1); break; - } - break; + } /* switch (packet[3] & 0xC) cases 0x00 AND 0xC0 */ + break; /* case PSMOUSE_IMEX */ case PSMOUSE_GENPS: /* Report scroll buttons on NetMice */