Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: alps - don't handle ALPS cs19 trackpoint-only device

On a latest Lenovo laptop, the trackpoint and 3 buttons below it
don't work at all, when we move the trackpoint or press those 3
buttons, the kernel will print out:
"Rejected trackstick packet from non DualPoint device"

This device is identified as an alps touchpad but the packet has
trackpoint format, so the alps.c drops the packet and prints out
the message above.

According to XiaoXiao's explanation, this device is named cs19 and
is trackpoint-only device, its firmware is only for trackpoint, it
is independent of touchpad and is a device completely different from
DualPoint ones.

To drive this device with mininal changes to the existing driver, we
just let the alps driver not handle this device, then the trackpoint.c
will be the driver of this device if the trackpoint driver is enabled.
(if not, this device will fallback to a bare PS/2 device)

With the trackpoint.c, this trackpoint and 3 buttons all work well,
they have all features that the trackpoint should have, like
scrolling-screen, drag-and-drop and frame-selection.

Signed-off-by: XiaoXiao Liu <sliuuxiaonxiao@gmail.com>
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Reviewed-by: Pali Rohár <pali.rohar@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

authored by

Hui Wang and committed by
Dmitry Torokhov
7e4935cc 88f28e95

+32
+32
drivers/input/mouse/alps.c
··· 21 21 22 22 #include "psmouse.h" 23 23 #include "alps.h" 24 + #include "trackpoint.h" 24 25 25 26 /* 26 27 * Definitions for ALPS version 3 and 4 command mode protocol ··· 2862 2861 return NULL; 2863 2862 } 2864 2863 2864 + static bool alps_is_cs19_trackpoint(struct psmouse *psmouse) 2865 + { 2866 + u8 param[2] = { 0 }; 2867 + 2868 + if (ps2_command(&psmouse->ps2dev, 2869 + param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) 2870 + return false; 2871 + 2872 + /* 2873 + * param[0] contains the trackpoint device variant_id while 2874 + * param[1] contains the firmware_id. So far all alps 2875 + * trackpoint-only devices have their variant_ids equal 2876 + * TP_VARIANT_ALPS and their firmware_ids are in 0x20~0x2f range. 2877 + */ 2878 + return param[0] == TP_VARIANT_ALPS && (param[1] & 0x20); 2879 + } 2880 + 2865 2881 static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) 2866 2882 { 2867 2883 const struct alps_protocol_info *protocol; ··· 3178 3160 error = alps_identify(psmouse, NULL); 3179 3161 if (error) 3180 3162 return error; 3163 + 3164 + /* 3165 + * ALPS cs19 is a trackpoint-only device, and uses different 3166 + * protocol than DualPoint ones, so we return -EINVAL here and let 3167 + * trackpoint.c drive this device. If the trackpoint driver is not 3168 + * enabled, the device will fall back to a bare PS/2 mouse. 3169 + * If ps2_command() fails here, we depend on the immediately 3170 + * followed psmouse_reset() to reset the device to normal state. 3171 + */ 3172 + if (alps_is_cs19_trackpoint(psmouse)) { 3173 + psmouse_dbg(psmouse, 3174 + "ALPS CS19 trackpoint-only device detected, ignoring\n"); 3175 + return -EINVAL; 3176 + } 3181 3177 3182 3178 /* 3183 3179 * Reset the device to make sure it is fully operational: