From: Christophe TORDEUX <christophe@xxxxxxxxxxx> With kernel v4.6 and later, the Sentelic touchpad STL3888_C0 and probably other Sentelic FSP touchpads are detected as a BYD touchpad and lose multitouch features. During the BYD handshake in the byd_detect function, the BYD driver mistakenly interprets a standard PS/2 protocol status request answer from the Sentelic touchpad as a successful handshake with a BYD touchpad. This is clearly a bug of the BYD driver. Description of the patch: In byd_detect function, remove positive detection result based on standard PS/2 protocol status request answer. Replace it with positive detection based on handshake answers as they can be inferred from the BYD touchpad datasheets found on BYD website. Signed-off-by: Christophe TORDEUX <christophe@xxxxxxxxxxx> --- Comments/discussion: A Sentelic touchpad STL3888_C0 is available to the author of this patch. No BYD touchpad device is available to the author of this patch for testing purpose. The BYD website contains 5 data sheets documents for 5 touchpads. Unfortunately the handshake procedure description from the BYD datasheets is either not fully consistent or not fully detailed. This means that while the author is positive the bug of Sentelic greedy detection is fixed by this patch, the effect on detection of BYD touchpads is not tested on actual hardware. But, because this patch codes the detection according to expected handshake answers based on BYD datasheets, the approach taken by this patch is probably the best in the author's opinion. Nevertheless alternatives can be considered. Alternative 1: move the detection of Sentelic touchpads above the detection of BYD touchpads in psmouse_try_protocol function. However based on the code comments, this could have adverse effects which I don't really know about. Alternative2: Sentelic STL3888_C0 answers E9 status request with a standard PS/2 protocol answer, however I found out my Sentelic STL3888_C0 answers E8/00/E8/00/E8/00/E8/00/E9 with 00/88/64, which looks like a handshake answer. This could be used as a test to exit the byd_detect function. Still effect on detection of a BYD device is not known. --- drivers/input/mouse/byd.c | 76 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/drivers/input/mouse/byd.c b/drivers/input/mouse/byd.c index b27aa63..b5acca0 100644 --- a/drivers/input/mouse/byd.c +++ b/drivers/input/mouse/byd.c @@ -35,6 +35,18 @@ * BYD pad constants */ +/* Handshake answer of BTP6034 */ +#define BYD_MODEL_BTP6034 0x00E801 +/* Handshake answer of BTP6740 */ +#define BYD_MODEL_BTP6740 0x001155 +/* Handshake answers of BTP8644, BTP10463 and BTP11484 */ +#define BYD_MODEL_BTP8644 0x011155 + +/* Handshake SETRES byte of BTP6034 and BTP6740 */ +#define BYD_SHAKE_BYTE_A 0x00 +/* Handshake SETRES byte of BTP8644, BTP10463 and BTP11484 */ +#define BYD_SHAKE_BYTE_B 0x03 + /* * True device resolution is unknown, however experiments show the * resolution is about 111 units/mm. @@ -434,23 +446,59 @@ static void byd_disconnect(struct psmouse *psmouse) } } +u32 byd_try_model(u32 model) +{ + size_t i; + + u32 byd_model[] = { + BYD_MODEL_BTP6034, + BYD_MODEL_BTP6740, + BYD_MODEL_BTP8644 + }; + + for (i=0; i < ARRAY_SIZE(byd_model); i++) { + if (model == byd_model[i]) + return model; + } + + return 0; +} + int byd_detect(struct psmouse *psmouse, bool set_properties) { struct ps2dev *ps2dev = &psmouse->ps2dev; - u8 param[4] = {0x03, 0x00, 0x00, 0x00}; - - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) - return -1; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) - return -1; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) - return -1; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) - return -1; - if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) - return -1; - - if (param[1] != 0x03 || param[2] != 0x64) + size_t i; + + u8 byd_shbyte[] = { + BYD_SHAKE_BYTE_A, + BYD_SHAKE_BYTE_B + }; + + bool detect = false; + for (i=0; i < ARRAY_SIZE(byd_shbyte); i++) { + u32 model; + u8 param[4] = {byd_shbyte[i], 0x00, 0x00, 0x00}; + + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) + return -1; + if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) + return -1; + + model = param[2]; + model += param[1] << 8; + model += param[0] << 16; + model = byd_try_model(model); + if (model) + detect = true; + } + + if (!detect) return -ENODEV; psmouse_dbg(psmouse, "BYD touchpad detected\n");
Attachment:
signature.asc
Description: PGP signature