^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ALPS touchpad PS/2 mouse driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * ALPS detection, tap switching and status querying info is taken from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * tpconfig utility (by C. Scott Ananian and Bruce Kall).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/input.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/input/mt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/serio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/libps2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/dmi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "psmouse.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "alps.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "trackpoint.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Definitions for ALPS version 3 and 4 command mode protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define ALPS_CMD_NIBBLE_10 0x01f2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ALPS_REG_BASE_RUSHMORE 0xc2c0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ALPS_REG_BASE_V7 0xc2c0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define ALPS_REG_BASE_PINNACLE 0x0000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) { PSMOUSE_CMD_SETRES, 0x00 }, /* a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) { PSMOUSE_CMD_SETRES, 0x01 }, /* b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) { PSMOUSE_CMD_SETRES, 0x02 }, /* c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) { PSMOUSE_CMD_SETRES, 0x03 }, /* d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define ALPS_PASS 0x04 /* device has a pass-through port */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define ALPS_WHEEL 0x08 /* hardware wheel present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define ALPS_FW_BK_1 0x10 /* front & back buttons present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define ALPS_FW_BK_2 0x20 /* front & back buttons present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 6-byte ALPS packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) #define ALPS_STICK_BITS 0x100 /* separate stick button bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) #define ALPS_DUALPOINT_WITH_PRESSURE 0x400 /* device can report trackpoint pressure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct alps_model_info alps_model_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * XXX This entry is suspicious. First byte has zero lower nibble,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * which is what a normal mouse would report. Also, the value 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * isn't valid per PS/2 spec.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { { 0x20, 0x02, 0x0e }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { { 0x22, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { { 0x22, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D600 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { { 0x32, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { { 0x33, 0x02, 0x0a }, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } }, /* UMAX-530T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { { 0x52, 0x01, 0x14 }, { ALPS_PROTO_V2, 0xff, 0xff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Toshiba Tecra A11-11L */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { { 0x53, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { { 0x53, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { { 0x60, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } }, /* HP ze1115 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { { 0x62, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xcf, 0xcf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { { 0x63, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { { 0x63, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { { 0x63, 0x02, 0x28 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Fujitsu Siemens S6010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) { { 0x63, 0x02, 0x3c }, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } }, /* Toshiba Satellite S2400-103 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) { { 0x63, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } }, /* NEC Versa L320 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) { { 0x63, 0x02, 0x64 }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) { { 0x63, 0x03, 0xc8 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D800 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) { { 0x73, 0x00, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } }, /* ThinkPad R61 8918-5QG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) { { 0x73, 0x00, 0x14 }, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } }, /* Dell XT2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) { { 0x73, 0x02, 0x0a }, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) { { 0x73, 0x02, 0x14 }, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Ahtec Laptop */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) { { 0x73, 0x02, 0x50 }, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } }, /* Dell Vostro 1400 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static const struct alps_protocol_info alps_v3_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static const struct alps_protocol_info alps_v3_rushmore_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const struct alps_protocol_info alps_v4_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ALPS_PROTO_V4, 0x8f, 0x8f, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static const struct alps_protocol_info alps_v5_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ALPS_PROTO_V5, 0xc8, 0xd8, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static const struct alps_protocol_info alps_v7_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT | ALPS_DUALPOINT_WITH_PRESSURE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static const struct alps_protocol_info alps_v8_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) ALPS_PROTO_V8, 0x18, 0x18, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static const struct alps_protocol_info alps_v9_protocol_data = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ALPS_PROTO_V9, 0xc8, 0xc8, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * Some v2 models report the stick buttons in separate bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static const struct dmi_system_id alps_dmi_has_separate_stick_buttons[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) #if defined(CONFIG_DMI) && defined(CONFIG_X86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* Extrapolated from other entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D420"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Reported-by: Hans de Bruin <jmdebruin@xmsnet.nl> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D430"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D620"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* Extrapolated from other entries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) .matches = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D630"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static void alps_set_abs_params_st(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct input_dev *dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void alps_set_abs_params_semi_mt(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) struct input_dev *dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static void alps_set_abs_params_v7(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) struct input_dev *dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) struct input_dev *dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Packet formats are described in Documentation/input/devices/alps.rst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static bool alps_is_valid_first_byte(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) unsigned char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return (data & priv->mask0) == priv->byte0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) static void alps_report_buttons(struct input_dev *dev1, struct input_dev *dev2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) int left, int right, int middle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) struct input_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * If shared button has already been reported on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * other device (dev2) then this event should be also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * sent through that device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) dev = (dev2 && test_bit(BTN_LEFT, dev2->key)) ? dev2 : dev1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) input_report_key(dev, BTN_LEFT, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) dev = (dev2 && test_bit(BTN_RIGHT, dev2->key)) ? dev2 : dev1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) input_report_key(dev, BTN_RIGHT, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) dev = (dev2 && test_bit(BTN_MIDDLE, dev2->key)) ? dev2 : dev1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) input_report_key(dev, BTN_MIDDLE, middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * Sync the _other_ device now, we'll do the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * device later once we report the rest of the events.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (dev2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) static void alps_process_packet_v1_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct input_dev *dev2 = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int x, y, z, ges, fin, left, right, middle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int back = 0, forward = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (priv->proto_version == ALPS_PROTO_V1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) left = packet[2] & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) right = packet[2] & 0x08;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) middle = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) x = packet[1] | ((packet[0] & 0x07) << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) y = packet[4] | ((packet[3] & 0x07) << 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) z = packet[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) left = packet[3] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) right = packet[3] & 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) middle = packet[3] & 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) z = packet[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (priv->flags & ALPS_FW_BK_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) back = packet[0] & 0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) forward = packet[2] & 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (priv->flags & ALPS_FW_BK_2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) back = packet[3] & 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) forward = packet[2] & 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if ((middle = forward && back))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) forward = back = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) ges = packet[2] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) fin = packet[2] & 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if ((priv->flags & ALPS_DUALPOINT) && z == 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) alps_report_buttons(dev2, dev, left, right, middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Some models have separate stick button bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (priv->flags & ALPS_STICK_BITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) left |= packet[0] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) right |= packet[0] & 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) middle |= packet[0] & 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) alps_report_buttons(dev, dev2, left, right, middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* Convert hardware tap to a reasonable Z value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (ges && !fin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) z = 40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * A "tap and drag" operation is reported by the hardware as a transition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * from (!fin && ges) to (fin && ges). This should be translated to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) if (ges && fin && !priv->prev_fin) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) input_report_abs(dev, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) input_report_abs(dev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) input_report_abs(dev, ABS_PRESSURE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) input_report_key(dev, BTN_TOOL_FINGER, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) priv->prev_fin = fin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (z > 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) input_report_key(dev, BTN_TOUCH, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (z < 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) input_report_key(dev, BTN_TOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (z > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) input_report_abs(dev, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) input_report_abs(dev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) input_report_abs(dev, ABS_PRESSURE, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) input_report_key(dev, BTN_TOOL_FINGER, z > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (priv->flags & ALPS_WHEEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) input_report_key(dev, BTN_FORWARD, forward);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) input_report_key(dev, BTN_BACK, back);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (priv->flags & ALPS_FOUR_BUTTONS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) input_report_key(dev, BTN_0, packet[2] & 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) input_report_key(dev, BTN_1, packet[0] & 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) input_report_key(dev, BTN_2, packet[3] & 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) input_report_key(dev, BTN_3, packet[0] & 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static void alps_get_bitmap_points(unsigned int map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) struct alps_bitmap_point *low,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct alps_bitmap_point *high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) int *fingers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct alps_bitmap_point *point;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) int i, bit, prev_bit = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) point = low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) for (i = 0; map != 0; i++, map >>= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) bit = map & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (!prev_bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) point->start_bit = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) point->num_bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) (*fingers)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) point->num_bits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (prev_bit)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) point = high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) prev_bit = bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * Process bitmap data from semi-mt protocols. Returns the number of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * fingers detected. A return value of 0 means at least one of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) * bitmaps was empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * The bitmaps don't have enough data to track fingers, so this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * only generates points representing a bounding box of all contacts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * These points are returned in fields->mt when the return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * is greater than 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static int alps_process_bitmap(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct alps_fields *fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int i, fingers_x = 0, fingers_y = 0, fingers, closest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct alps_bitmap_point x_low = {0,}, x_high = {0,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct alps_bitmap_point y_low = {0,}, y_high = {0,};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct input_mt_pos corner[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (!fields->x_map || !fields->y_map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * Fingers can overlap, so we use the maximum count of fingers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * on either axis as the finger count.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) fingers = max(fingers_x, fingers_y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * If an axis reports only a single contact, we have overlapping or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * adjacent fingers. Divide the single contact between the two points.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (fingers_x == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) i = (x_low.num_bits - 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) x_low.num_bits = x_low.num_bits - i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) x_high.start_bit = x_low.start_bit + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) x_high.num_bits = max(i, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (fingers_y == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) i = (y_low.num_bits - 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) y_low.num_bits = y_low.num_bits - i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) y_high.start_bit = y_low.start_bit + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) y_high.num_bits = max(i, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* top-left corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) corner[0].x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) (2 * (priv->x_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) corner[0].y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) (2 * (priv->y_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* top-right corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) corner[1].x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) (2 * (priv->x_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) corner[1].y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) (2 * (priv->y_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* bottom-right corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) corner[2].x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) (2 * (priv->x_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) corner[2].y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) (2 * (priv->y_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* bottom-left corner */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) corner[3].x =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) (2 * (priv->x_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) corner[3].y =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) (2 * (priv->y_bits - 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* x-bitmap order is reversed on v5 touchpads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (priv->proto_version == ALPS_PROTO_V5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) corner[i].x = priv->x_max - corner[i].x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* y-bitmap order is reversed on v3 and v4 touchpads */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (priv->proto_version == ALPS_PROTO_V3 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) priv->proto_version == ALPS_PROTO_V4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) for (i = 0; i < 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) corner[i].y = priv->y_max - corner[i].y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * We only select a corner for the second touch once per 2 finger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * touch sequence to avoid the chosen corner (and thus the coordinates)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * jumping around when the first touch is in the middle.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (priv->second_touch == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* Find corner closest to our st coordinates */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) closest = 0x7fffffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int dx = fields->st.x - corner[i].x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int dy = fields->st.y - corner[i].y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) int distance = dx * dx + dy * dy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (distance < closest) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) priv->second_touch = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) closest = distance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* And select the opposite corner to use for the 2nd touch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) priv->second_touch = (priv->second_touch + 2) % 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) fields->mt[0] = fields->st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) fields->mt[1] = corner[priv->second_touch];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) input_mt_slot(dev, slot);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) input_report_abs(dev, ABS_MT_POSITION_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) input_report_abs(dev, ABS_MT_POSITION_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static void alps_report_mt_data(struct psmouse *psmouse, int n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) int i, slot[MAX_TOUCHES];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) input_mt_assign_slots(dev, slot, f->mt, n, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) for (i = 0; i < n; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) input_mt_sync_frame(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* Use st data when we don't have mt data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (fingers < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) f->mt[0].x = f->st.x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) f->mt[0].y = f->st.y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) fingers = f->pressure > 0 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) priv->second_touch = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (fingers >= 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) alps_set_slot(dev, 0, f->mt[0].x, f->mt[0].y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) if (fingers >= 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) alps_set_slot(dev, 1, f->mt[1].x, f->mt[1].y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) input_mt_sync_frame(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) input_mt_report_finger_count(dev, fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) input_report_key(dev, BTN_LEFT, f->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) input_report_key(dev, BTN_RIGHT, f->right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) input_report_key(dev, BTN_MIDDLE, f->middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) input_report_abs(dev, ABS_PRESSURE, f->pressure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct input_dev *dev = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int x, y, z, left, right, middle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* It should be a DualPoint when received trackstick packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (!(priv->flags & ALPS_DUALPOINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) psmouse_warn(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) "Rejected trackstick packet from non DualPoint device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) /* Sanity check packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (!(packet[0] & 0x40)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * There's a special packet that seems to indicate the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * of a stream of trackstick data. Filter these out.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) z = packet[4] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * The x and y values tend to be quite large, and when used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) * alone the trackstick is difficult to use. Scale them down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * to compensate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) x /= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) y /= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) input_report_rel(dev, REL_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) input_report_rel(dev, REL_Y, -y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) input_report_abs(dev, ABS_PRESSURE, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * Most ALPS models report the trackstick buttons in the touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * packets, but a few report them here. No reliable way has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * found to differentiate between the models upfront, so we enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * the quirk in response to seeing a button press in the trackstick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) left = packet[3] & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) right = packet[3] & 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) middle = packet[3] & 0x04;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) (left || right || middle))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) input_report_key(dev, BTN_LEFT, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) input_report_key(dev, BTN_RIGHT, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) input_report_key(dev, BTN_MIDDLE, middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) f->left = !!(p[3] & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) f->right = !!(p[3] & 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) f->middle = !!(p[3] & 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) f->ts_left = !!(p[3] & 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) f->ts_right = !!(p[3] & 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) f->ts_middle = !!(p[3] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) f->first_mp = !!(p[4] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) f->is_mp = !!(p[0] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (f->is_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) f->fingers = (p[5] & 0x3) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) f->x_map = ((p[4] & 0x7e) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ((p[1] & 0x7f) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) ((p[0] & 0x30) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) f->y_map = ((p[3] & 0x70) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) ((p[2] & 0x7f) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) (p[4] & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) ((p[0] & 0x30) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) f->pressure = p[5] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) alps_decode_buttons_v3(f, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) f->first_mp = !!(p[4] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) f->is_mp = !!(p[5] & 0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (f->is_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) f->x_map = ((p[5] & 0x10) << 11) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) ((p[4] & 0x7e) << 8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) ((p[1] & 0x7f) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) ((p[0] & 0x30) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) f->y_map = ((p[5] & 0x20) << 6) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) ((p[3] & 0x70) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) ((p[2] & 0x7f) << 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) (p[4] & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ((p[0] & 0x30) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) f->pressure = p[5] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) alps_decode_buttons_v3(f, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) u64 palm_data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) f->first_mp = !!(p[0] & 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) f->is_mp = !!(p[0] & 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (!f->is_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) alps_decode_buttons_v3(f, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) f->fingers = ((p[0] & 0x6) >> 1 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) (p[0] & 0x10) >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) palm_data = (p[1] & 0x7f) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) ((p[2] & 0x7f) << 7) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) ((p[4] & 0x7f) << 14) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ((p[5] & 0x7f) << 21) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) ((p[3] & 0x07) << 28) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) (((u64)p[3] & 0x70) << 27) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) (((u64)p[0] & 0x01) << 34);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) f->y_map = palm_data & (BIT(priv->y_bits) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) f->x_map = (palm_data >> priv->y_bits) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) (BIT(priv->x_bits) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) struct input_dev *dev2 = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) int fingers = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) memset(f, 0, sizeof(*f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) priv->decode_fields(f, packet, psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) * There's no single feature of touchpad position and bitmap packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) * that can be used to distinguish between them. We rely on the fact
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) * that a bitmap packet should always follow a position packet with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) * bit 6 of packet[4] set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (priv->multi_packet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) * Sometimes a position packet will indicate a multi-packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) * sequence, but then what follows is another position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) * packet. Check for this, and when it happens process the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) * position packet as usual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (f->is_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) fingers = f->fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * Bitmap processing uses position packet's coordinate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * data, so we need to do decode it first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) priv->decode_fields(f, priv->multi_data, psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (alps_process_bitmap(priv, f) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) fingers = 0; /* Use st data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * Bit 6 of byte 0 is not usually set in position packets. The only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * times it seems to be set is in situations where the data is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * suspect anyway, e.g. a palm resting flat on the touchpad. Given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * this combined with the fact that this bit is useful for filtering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * out misidentified bitmap packets, we reject anything with this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * bit set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (f->is_mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (!priv->multi_packet && f->first_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) priv->multi_packet = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * Sometimes the hardware sends a single packet with z = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * in the middle of a stream. Real releases generate packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * with x, y, and z all zero, so these seem to be flukes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) * Ignore them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (f->st.x && f->st.y && !f->pressure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) alps_report_semi_mt_data(psmouse, fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) if ((priv->flags & ALPS_DUALPOINT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) !(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) input_report_key(dev2, BTN_LEFT, f->ts_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) input_report_key(dev2, BTN_RIGHT, f->ts_right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static void alps_process_packet_v3(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * v3 protocol packets come in three types, two representing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * touchpad data and one representing trackstick data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * Trackstick packets seem to be distinguished by always
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * having 0x3f in the last byte. This value has never been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * observed in the last byte of either of the other types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * of packets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (packet[5] == 0x3f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) alps_process_trackstick_packet_v3(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) alps_process_touchpad_packet_v3_v5(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) static void alps_process_packet_v6(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct input_dev *dev2 = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) int x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) * We can use Byte5 to distinguish if the packet is from Touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * or Trackpoint.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * Touchpad: 0 - 0x7E
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * Trackpoint: 0x7F
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) if (packet[5] == 0x7F) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) /* It should be a DualPoint when received Trackpoint packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (!(priv->flags & ALPS_DUALPOINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) psmouse_warn(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) "Rejected trackstick packet from non DualPoint device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) /* Trackpoint packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) x = packet[1] | ((packet[3] & 0x20) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) y = packet[2] | ((packet[3] & 0x40) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) z = packet[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) /* To prevent the cursor jump when finger lifted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (x == 0x7F && y == 0x7F && z == 0x7F)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) x = y = z = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) /* Divide 4 since trackpoint's speed is too fast */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) input_report_rel(dev2, REL_X, (char)x / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) input_report_rel(dev2, REL_Y, -((char)y / 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) psmouse_report_standard_buttons(dev2, packet[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /* Touchpad packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) x = packet[1] | ((packet[3] & 0x78) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) y = packet[2] | ((packet[4] & 0x78) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) z = packet[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) if (z > 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) input_report_key(dev, BTN_TOUCH, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) if (z < 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) input_report_key(dev, BTN_TOUCH, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (z > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) input_report_abs(dev, ABS_X, x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) input_report_abs(dev, ABS_Y, y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) input_report_abs(dev, ABS_PRESSURE, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) input_report_key(dev, BTN_TOOL_FINGER, z > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* v6 touchpad does not have middle button */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) packet[3] &= ~BIT(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) psmouse_report_standard_buttons(dev2, packet[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) static void alps_process_packet_v4(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) * v4 has a 6-byte encoding for bitmap data, but this data is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * broken up between 3 normal packets. Use priv->multi_packet to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * track our position in the bitmap packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) if (packet[6] & 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /* sync, reset position */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (WARN_ON_ONCE(priv->multi_packet > 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) offset = 2 * priv->multi_packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) priv->multi_data[offset] = packet[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) priv->multi_data[offset + 1] = packet[7];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) f->left = !!(packet[4] & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) f->right = !!(packet[4] & 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) ((packet[0] & 0x30) >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) f->pressure = packet[5] & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (++priv->multi_packet > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) ((priv->multi_data[3] & 0x60) << 3) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) ((priv->multi_data[0] & 0x3f) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) ((priv->multi_data[1] & 0x60) >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) ((priv->multi_data[3] & 0x1f) << 5) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) (priv->multi_data[1] & 0x1f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) f->fingers = alps_process_bitmap(priv, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) alps_report_semi_mt_data(psmouse, f->fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) static bool alps_is_valid_package_v7(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) switch (psmouse->pktcnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) return (psmouse->packet[2] & 0x40) == 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return (psmouse->packet[3] & 0x48) == 0x48;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) return (psmouse->packet[5] & 0x40) == 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static unsigned char alps_get_packet_id_v7(char *byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) unsigned char packet_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (byte[4] & 0x40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) packet_id = V7_PACKET_ID_TWO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) else if (byte[4] & 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) packet_id = V7_PACKET_ID_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) packet_id = V7_PACKET_ID_NEW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) else if (byte[1] == 0x00 && byte[4] == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) packet_id = V7_PACKET_ID_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) packet_id = V7_PACKET_ID_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) return packet_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) unsigned char *pkt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) unsigned char pkt_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) mt[0].x = ((pkt[2] & 0x80) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) mt[0].x |= ((pkt[2] & 0x3F) << 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) mt[0].x |= ((pkt[3] & 0x30) >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mt[0].x |= (pkt[3] & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) mt[1].x = ((pkt[3] & 0x80) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) mt[1].x |= ((pkt[4] & 0x80) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) mt[1].x |= ((pkt[4] & 0x3F) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) mt[1].y = ((pkt[5] & 0x80) << 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) mt[1].y |= ((pkt[5] & 0x3F) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) switch (pkt_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) case V7_PACKET_ID_TWO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) mt[1].x &= ~0x000F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) mt[1].y |= 0x000F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Detect false-postive touches where x & y report max value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (mt[1].y == 0x7ff && mt[1].x == 0xff0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) mt[1].x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* y gets set to 0 at the end of this function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) case V7_PACKET_ID_MULTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) mt[1].x &= ~0x003F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mt[1].y &= ~0x0020;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) mt[1].y |= ((pkt[4] & 0x02) << 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) mt[1].y |= 0x001F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) case V7_PACKET_ID_NEW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) mt[1].x &= ~0x003F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) mt[1].x |= (pkt[0] & 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) mt[1].y |= 0x000F;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) mt[0].y = 0x7FF - mt[0].y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) mt[1].y = 0x7FF - mt[1].y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int alps_get_mt_count(struct input_mt_pos *mt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) int i, fingers = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) for (i = 0; i < MAX_TOUCHES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (mt[i].x != 0 || mt[i].y != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) fingers++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return fingers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) static int alps_decode_packet_v7(struct alps_fields *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) unsigned char *p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) unsigned char pkt_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) pkt_id = alps_get_packet_id_v7(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (pkt_id == V7_PACKET_ID_IDLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (pkt_id == V7_PACKET_ID_UNKNOWN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) * NEW packets are send to indicate a discontinuity in the finger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * coordinate reporting. Specifically a finger may have moved from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * slot 0 to 1 or vice versa. INPUT_MT_TRACK takes care of this for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) * us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * NEW packets have 3 problems:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * 1) They do not contain middle / right button info (on non clickpads)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * this can be worked around by preserving the old button state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * 2) They do not contain an accurate fingercount, and they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * typically send when the number of fingers changes. We cannot use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) * the old finger count as that may mismatch with the amount of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * touch coordinates we've available in the NEW packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * 3) Their x data for the second touch is inaccurate leading to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) * a possible jump of the x coordinate by 16 units when the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) * non NEW packet comes in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) * Since problems 2 & 3 cannot be worked around, just ignore them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (pkt_id == V7_PACKET_ID_NEW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) if (pkt_id == V7_PACKET_ID_TWO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) f->fingers = alps_get_mt_count(f->mt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) else /* pkt_id == V7_PACKET_ID_MULTI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) f->fingers = 3 + (p[5] & 0x03);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) f->left = (p[0] & 0x80) >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (priv->flags & ALPS_BUTTONPAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) if (p[0] & 0x20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) f->fingers++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (p[0] & 0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) f->fingers++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) f->right = (p[0] & 0x20) >> 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) f->middle = (p[0] & 0x10) >> 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) /* Sometimes a single touch is reported in mt[1] rather then mt[0] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (f->fingers == 1 && f->mt[0].x == 0 && f->mt[0].y == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) f->mt[0].x = f->mt[1].x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) f->mt[0].y = f->mt[1].y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) f->mt[1].x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) f->mt[1].y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) struct input_dev *dev2 = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) int x, y, z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* It should be a DualPoint when received trackstick packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (!(priv->flags & ALPS_DUALPOINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) psmouse_warn(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) "Rejected trackstick packet from non DualPoint device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) ((packet[3] & 0x20) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) input_report_rel(dev2, REL_X, (char)x);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) input_report_rel(dev2, REL_Y, -((char)y));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) input_report_abs(dev2, ABS_PRESSURE, z);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) psmouse_report_standard_buttons(dev2, packet[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) memset(f, 0, sizeof(*f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (priv->decode_fields(f, psmouse->packet, psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) input_mt_report_finger_count(dev, f->fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) input_report_key(dev, BTN_LEFT, f->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) input_report_key(dev, BTN_RIGHT, f->right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) input_report_key(dev, BTN_MIDDLE, f->middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) static void alps_process_packet_v7(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) alps_process_trackstick_packet_v7(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) alps_process_touchpad_packet_v7(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) static enum SS4_PACKET_ID alps_get_pkt_id_ss4_v2(unsigned char *byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) enum SS4_PACKET_ID pkt_id = SS4_PACKET_ID_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) switch (byte[3] & 0x30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) case 0x00:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) if (SS4_IS_IDLE_V2(byte)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) pkt_id = SS4_PACKET_ID_IDLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) pkt_id = SS4_PACKET_ID_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) case 0x10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) /* two-finger finger positions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) pkt_id = SS4_PACKET_ID_TWO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) case 0x20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) /* stick pointer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) pkt_id = SS4_PACKET_ID_STICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) case 0x30:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /* third and fourth finger positions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) pkt_id = SS4_PACKET_ID_MULTI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) return pkt_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int alps_decode_ss4_v2(struct alps_fields *f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) unsigned char *p, struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) enum SS4_PACKET_ID pkt_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) unsigned int no_data_x, no_data_y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) pkt_id = alps_get_pkt_id_ss4_v2(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) /* Current packet is 1Finger coordinate packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) switch (pkt_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) case SS4_PACKET_ID_ONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) f->mt[0].x = SS4_1F_X_V2(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) f->mt[0].y = SS4_1F_Y_V2(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) * When a button is held the device will give us events
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) * with x, y, and pressure of 0. This causes annoying jumps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) * if a touch is released while the button is held.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) * Handle this by claiming zero contacts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) f->fingers = f->pressure > 0 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) f->first_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) f->is_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) case SS4_PACKET_ID_TWO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) if (priv->flags & ALPS_BUTTONPAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) f->mt[0].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) f->mt[1].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) f->mt[0].x = SS4_BTL_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) f->mt[1].x = SS4_BTL_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) f->mt[0].x = SS4_PLUS_STD_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) f->mt[1].x = SS4_PLUS_STD_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) f->mt[0].x = SS4_STD_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) f->mt[1].x = SS4_STD_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) f->mt[0].y = SS4_STD_MF_Y_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) f->mt[1].y = SS4_STD_MF_Y_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) if (SS4_IS_MF_CONTINUE(p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) f->first_mp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) f->fingers = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) f->first_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) f->is_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) case SS4_PACKET_ID_MULTI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) if (priv->flags & ALPS_BUTTONPAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) f->mt[2].x = SS4_PLUS_BTL_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) f->mt[3].x = SS4_PLUS_BTL_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) no_data_x = SS4_PLUS_MFPACKET_NO_AX_BL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) f->mt[2].x = SS4_BTL_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) f->mt[3].x = SS4_BTL_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) no_data_x = SS4_MFPACKET_NO_AX_BL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) no_data_y = SS4_MFPACKET_NO_AY_BL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) f->mt[2].x = SS4_PLUS_STD_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) f->mt[3].x = SS4_PLUS_STD_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) no_data_x = SS4_PLUS_MFPACKET_NO_AX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) f->mt[2].x = SS4_STD_MF_X_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) f->mt[3].x = SS4_STD_MF_X_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) no_data_x = SS4_MFPACKET_NO_AX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) no_data_y = SS4_MFPACKET_NO_AY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) f->mt[2].y = SS4_STD_MF_Y_V2(p, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) f->mt[3].y = SS4_STD_MF_Y_V2(p, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) f->first_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) f->is_mp = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if (SS4_IS_5F_DETECTED(p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) f->fingers = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) } else if (f->mt[3].x == no_data_x &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) f->mt[3].y == no_data_y) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) f->mt[3].x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) f->mt[3].y = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) f->fingers = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) f->fingers = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) case SS4_PACKET_ID_STICK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * x, y, and pressure are decoded in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * alps_process_packet_ss4_v2()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) f->first_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) f->is_mp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) case SS4_PACKET_ID_IDLE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) memset(f, 0, sizeof(struct alps_fields));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) /* handle buttons */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) if (pkt_id == SS4_PACKET_ID_STICK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) f->ts_left = !!(SS4_BTN_V2(p) & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) f->ts_right = !!(SS4_BTN_V2(p) & 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) f->ts_middle = !!(SS4_BTN_V2(p) & 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) f->left = !!(SS4_BTN_V2(p) & 0x01);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) if (!(priv->flags & ALPS_BUTTONPAD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) f->right = !!(SS4_BTN_V2(p) & 0x02);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) f->middle = !!(SS4_BTN_V2(p) & 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) unsigned char *packet = psmouse->packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) struct input_dev *dev = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) struct input_dev *dev2 = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) struct alps_fields *f = &priv->f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) memset(f, 0, sizeof(struct alps_fields));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) priv->decode_fields(f, packet, psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) if (priv->multi_packet) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * Sometimes the first packet will indicate a multi-packet
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * sequence, but sometimes the next multi-packet would not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) * come. Check for this, and when it happens process the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) * position packet as usual.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) if (f->is_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) /* Now process the 1st packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) priv->decode_fields(f, priv->multi_data, psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * "f.is_mp" would always be '0' after merging the 1st and 2nd packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * When it is set, it means 2nd packet comes without 1st packet come.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (f->is_mp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /* Save the first packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (!priv->multi_packet && f->first_mp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) priv->multi_packet = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) priv->multi_packet = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) /* Report trackstick */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) if (alps_get_pkt_id_ss4_v2(packet) == SS4_PACKET_ID_STICK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (!(priv->flags & ALPS_DUALPOINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) psmouse_warn(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) "Rejected trackstick packet from non DualPoint device");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) input_report_rel(dev2, REL_X, SS4_TS_X_V2(packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) input_report_rel(dev2, REL_Y, SS4_TS_Y_V2(packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) input_report_abs(dev2, ABS_PRESSURE, SS4_TS_Z_V2(packet));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) input_report_key(dev2, BTN_LEFT, f->ts_left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) input_report_key(dev2, BTN_RIGHT, f->ts_right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) input_sync(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /* Report touchpad */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) input_mt_report_finger_count(dev, f->fingers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) input_report_key(dev, BTN_LEFT, f->left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) input_report_key(dev, BTN_RIGHT, f->right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) input_report_key(dev, BTN_MIDDLE, f->middle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) input_report_abs(dev, ABS_PRESSURE, f->pressure);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) static DEFINE_MUTEX(alps_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) static void alps_register_bare_ps2_mouse(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) struct alps_data *priv =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) container_of(work, struct alps_data, dev3_register_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) struct psmouse *psmouse = priv->psmouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct input_dev *dev3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) mutex_lock(&alps_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) if (priv->dev3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) dev3 = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) if (!dev3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) psmouse_err(psmouse, "failed to allocate secondary device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) psmouse->ps2dev.serio->phys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) (priv->dev2 ? "input2" : "input1"));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) dev3->phys = priv->phys3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * format of input device name is: "protocol vendor name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * see function psmouse_switch_protocol() in psmouse-base.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) dev3->name = "PS/2 ALPS Mouse";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) dev3->id.bustype = BUS_I8042;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) dev3->id.vendor = 0x0002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) dev3->id.product = PSMOUSE_PS2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) dev3->id.version = 0x0000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) dev3->dev.parent = &psmouse->ps2dev.serio->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) input_set_capability(dev3, EV_REL, REL_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) input_set_capability(dev3, EV_REL, REL_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) input_set_capability(dev3, EV_KEY, BTN_LEFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) input_set_capability(dev3, EV_KEY, BTN_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) input_set_capability(dev3, EV_KEY, BTN_MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) __set_bit(INPUT_PROP_POINTER, dev3->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) error = input_register_device(dev3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) "failed to register secondary device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) input_free_device(dev3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) priv->dev3 = dev3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) * Save the error code so that we can detect that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) * already tried to create the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) priv->dev3 = ERR_PTR(error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) mutex_unlock(&alps_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) unsigned char packet[],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) bool report_buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) struct input_dev *dev, *dev2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) /* Figure out which device to use to report the bare packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (priv->proto_version == ALPS_PROTO_V2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) (priv->flags & ALPS_DUALPOINT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) /* On V2 devices the DualPoint Stick reports bare packets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) dev = priv->dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) dev2 = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) } else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) /* Register dev3 mouse if we received PS/2 packet first time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (!IS_ERR(priv->dev3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) psmouse_queue_work(psmouse, &priv->dev3_register_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) dev = priv->dev3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) if (report_buttons)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) alps_report_buttons(dev, dev2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) packet[0] & 1, packet[0] & 2, packet[0] & 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) psmouse_report_standard_motion(dev, packet);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) input_sync(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) if (psmouse->pktcnt < 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (psmouse->pktcnt == 6) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) * Start a timer to flush the packet if it ends up last
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * 6-byte packet in the stream. Timer needs to fire
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) * psmouse core times out itself. 20 ms should be enough
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) * to decide if we are getting more data or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) del_timer(&priv->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (psmouse->packet[6] & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) * Highest bit is set - that means we either had
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) * complete ALPS packet and this is start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) * next packet or we got garbage.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (((psmouse->packet[3] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) psmouse->packet[4] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) psmouse->packet[5]) & 0x80) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) "refusing packet %4ph (suspected interleaved ps/2)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) psmouse->packet + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return PSMOUSE_BAD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) priv->process_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) /* Continue with the next packet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) psmouse->packet[0] = psmouse->packet[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) psmouse->pktcnt = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) * High bit is 0 - that means that we indeed got a PS/2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) * packet in the middle of ALPS packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) * There is also possibility that we got 6-byte ALPS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) * packet followed by 3-byte packet from trackpoint. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) * can not distinguish between these 2 scenarios but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) * because the latter is unlikely to happen in course of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * normal operation (user would need to press all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) * buttons on the pad and start moving trackpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) * without touching the pad surface) we assume former.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) * Even if we are wrong the wost thing that would happen
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) * the cursor would jump but we should not get protocol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) * de-synchronization.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * Continue with the standard ALPS protocol handling,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) * but make sure we won't process it as an interleaved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * packet again, which may happen if all buttons are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) * pressed. To avoid this let's reset the 4th bit which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) * is normally 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) psmouse->packet[3] = psmouse->packet[6] & 0xf7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) psmouse->pktcnt = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) static void alps_flush_packet(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) struct alps_data *priv = from_timer(priv, t, timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) struct psmouse *psmouse = priv->psmouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) serio_pause_rx(psmouse->ps2dev.serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (psmouse->pktcnt == psmouse->pktsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) * We did not any more data in reasonable amount of time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) * Validate the last 3 bytes and process as a standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) * ALPS packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if ((psmouse->packet[3] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) psmouse->packet[4] |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) psmouse->packet[5]) & 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) "refusing packet %3ph (suspected interleaved ps/2)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) psmouse->packet + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) priv->process_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) psmouse->pktcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) serio_continue_rx(psmouse->ps2dev.serio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) * Check if we are dealing with a bare PS/2 packet, presumably from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) * a device connected to the external PS/2 port. Because bare PS/2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) * protocol does not have enough constant bits to self-synchronize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) * properly we only do this if the device is fully synchronized.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) * Can not distinguish V8's first byte from PS/2 packet's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) if (priv->proto_version != ALPS_PROTO_V8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) !psmouse->out_of_sync_cnt &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) (psmouse->packet[0] & 0xc8) == 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) if (psmouse->pktcnt == 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) alps_report_bare_ps2_packet(psmouse, psmouse->packet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return PSMOUSE_FULL_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) if ((priv->flags & ALPS_PS2_INTERLEAVED) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return alps_handle_interleaved_ps2(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) psmouse->packet[0], priv->mask0, priv->byte0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) return PSMOUSE_BAD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) /* Bytes 2 - pktsize should have 0 in the highest bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (priv->proto_version < ALPS_PROTO_V5 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) psmouse->pktcnt - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) psmouse->packet[psmouse->pktcnt - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) if (priv->proto_version == ALPS_PROTO_V3_RUSHMORE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) psmouse->pktcnt == psmouse->pktsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) * Some Dell boxes, such as Latitude E6440 or E7440
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) * with closed lid, quite often smash last byte of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * otherwise valid packet with 0xff. Given that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * next packet is very likely to be valid let's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * report PSMOUSE_FULL_PACKET but not process data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) * rather than reporting PSMOUSE_BAD_DATA and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * filling the logs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) return PSMOUSE_FULL_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) return PSMOUSE_BAD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) if ((priv->proto_version == ALPS_PROTO_V7 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) !alps_is_valid_package_v7(psmouse)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) (priv->proto_version == ALPS_PROTO_V8 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) !alps_is_valid_package_ss4_v2(psmouse))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) psmouse->pktcnt - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) psmouse->packet[psmouse->pktcnt - 1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) return PSMOUSE_BAD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (psmouse->pktcnt == psmouse->pktsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) priv->process_packet(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) return PSMOUSE_FULL_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) return PSMOUSE_GOOD_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) int command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) unsigned char *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) unsigned char dummy[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) BUG_ON(nibble > 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) command = priv->nibble_commands[nibble].command;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) param = (command & 0x0f00) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) dummy : (unsigned char *)&priv->nibble_commands[nibble].data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) if (ps2_command(ps2dev, param, command))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) int i, nibble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) if (ps2_command(ps2dev, NULL, priv->addr_command))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) for (i = 12; i >= 0; i -= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) nibble = (addr >> i) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (alps_command_mode_send_nibble(psmouse, nibble))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) * The address being read is returned in the first two bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) * of the result. Check that this address matches the expected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) * address.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) if (addr != ((param[0] << 8) | param[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) return param[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) if (alps_command_mode_set_addr(psmouse, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) return __alps_command_mode_read_reg(psmouse, addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (alps_command_mode_send_nibble(psmouse, value & 0xf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) u8 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) if (alps_command_mode_set_addr(psmouse, addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) return __alps_command_mode_write_reg(psmouse, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) int repeated_command, unsigned char *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) param[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) if (init_command && ps2_command(ps2dev, param, init_command))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) if (ps2_command(ps2dev, NULL, repeated_command) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) ps2_command(ps2dev, NULL, repeated_command) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) ps2_command(ps2dev, NULL, repeated_command))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) param[0] = param[1] = param[2] = 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) psmouse_dbg(psmouse, "%2.2X report: %3ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) repeated_command, param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) static bool alps_check_valid_firmware_id(unsigned char id[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) if (id[0] == 0x73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) if (id[0] == 0x88 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) (id[1] == 0x07 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) id[1] == 0x08 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) (id[1] & 0xf0) == 0xb0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) (id[1] & 0xf0) == 0xc0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) static int alps_enter_command_mode(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) psmouse_err(psmouse, "failed to enter command mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) if (!alps_check_valid_firmware_id(param)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) "unknown response while entering command mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) static inline int alps_exit_command_mode(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) * For DualPoint devices select the device that should respond to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) * subsequent commands. It looks like glidepad is behind stickpointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * I'd thought it would be other way around...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) if (ps2_command(ps2dev, NULL, cmd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) ps2_command(ps2dev, NULL, cmd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) ps2_command(ps2dev, NULL, cmd) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) /* we may get 3 more bytes, just ignore them */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) ps2_drain(ps2dev, 3, 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) /* Try ALPS magic knock - 4 disable before enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) * Switch mouse to poll (remote) mode so motion data will not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) * get in our way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) return ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) int i, nibble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) * b0-b11 are valid bits, send sequence is inverse.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) for (i = 0; i <= 8; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) nibble = (word >> i) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) if (alps_command_mode_send_nibble(psmouse, nibble))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) u16 addr, u16 value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) /* 0x0A0 is the command to write the word */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) alps_monitor_mode_send_word(psmouse, 0x0A0) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) alps_monitor_mode_send_word(psmouse, addr) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) alps_monitor_mode_send_word(psmouse, value) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) /* EC to exit monitor mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) static int alps_absolute_mode_v6(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) u16 reg_val = 0x181;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) /* enter monitor mode, to write the register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) if (alps_monitor_mode(psmouse, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) if (alps_monitor_mode(psmouse, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) static int alps_get_status(struct psmouse *psmouse, char *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) /* Get status: 0xF5 0xF5 0xF5 0xE9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) * Turn touchpad tapping on or off. The sequences are:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) * My guess that 0xE9 (GetInfo) is here as a sync point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) * For models that also have stickpointer (DualPoints) its tapping
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) * we don't fiddle with it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) static int alps_tap_mode(struct psmouse *psmouse, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) unsigned char tap_arg = enable ? 0x0A : 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) ps2_command(ps2dev, &tap_arg, cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) if (alps_get_status(psmouse, param))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) * alps_poll() - poll the touchpad for current motion packet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) * Used in resync.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) static int alps_poll(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) unsigned char buf[sizeof(psmouse->packet)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) bool poll_failed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) if (priv->flags & ALPS_PASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) alps_passthrough_mode_v2(psmouse, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) poll_failed = ps2_command(&psmouse->ps2dev, buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999) if (priv->flags & ALPS_PASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) alps_passthrough_mode_v2(psmouse, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) if (poll_failed || (buf[0] & priv->mask0) != priv->byte0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) if ((psmouse->badbyte & 0xc8) == 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) * Poll the track stick ...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) memcpy(psmouse->packet, buf, sizeof(buf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) static int alps_hw_init_v1_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) if ((priv->flags & ALPS_PASS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) alps_passthrough_mode_v2(psmouse, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) if (alps_tap_mode(psmouse, true)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) if (alps_absolute_mode_v1_v2(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) psmouse_err(psmouse, "Failed to enable absolute mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) if ((priv->flags & ALPS_PASS) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) alps_passthrough_mode_v2(psmouse, false)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) /* ALPS needs stream mode, otherwise it won't report any data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) psmouse_err(psmouse, "Failed to enable stream mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) /* Must be in passthrough mode when calling this function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) static int alps_trackstick_enter_extended_mode_v3_v6(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) unsigned char param[2] = {0xC8, 0x14};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) ps2_command(&psmouse->ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) ps2_command(&psmouse->ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) static int alps_hw_init_v6(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) if (alps_passthrough_mode_v2(psmouse, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) ret = alps_trackstick_enter_extended_mode_v3_v6(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) if (alps_passthrough_mode_v2(psmouse, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) if (alps_absolute_mode_v6(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) psmouse_err(psmouse, "Failed to enable absolute mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) * Enable or disable passthrough mode to the trackstick.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) static int alps_passthrough_mode_v3(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) int reg_base, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) int reg_val, ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) if (alps_enter_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) reg_val |= 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) reg_val &= ~0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) ret = __alps_command_mode_write_reg(psmouse, reg_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) if (alps_exit_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) /* Must be in command mode when calling this function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) static int alps_absolute_mode_v3(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120) int reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) reg_val |= 0x06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) if (__alps_command_mode_write_reg(psmouse, reg_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) static int alps_probe_trackstick_v3_v7(struct psmouse *psmouse, int reg_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135) int ret = -EIO, reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) if (alps_enter_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) /* bit 7: trackstick is present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) ret = reg_val & 0x80 ? 0 : -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) int reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) * We need to configure trackstick to report data for touchpad in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) * extended format. And also we need to tell touchpad to expect data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) * from trackstick in extended format. Without this configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) * trackstick packets sent from touchpad are in basic format which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) * different from what we expect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) if (alps_passthrough_mode_v3(psmouse, reg_base, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) * E7 report for the trackstick
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) * There have been reports of failures to seem to trace back
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) * to the above trackstick check failing. When these occur
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) * this E7 report fails, so when that happens we continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) * with the assumption that there isn't a trackstick after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) * all.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) if (alps_trackstick_enter_extended_mode_v3_v6(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) psmouse_err(psmouse, "Failed to enter into trackstick extended mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) if (alps_passthrough_mode_v3(psmouse, reg_base, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) if (alps_enter_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) if (reg_val == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2202) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2203) * Tell touchpad that trackstick is now in extended mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2204) * If bit 1 isn't set the packet format is different.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2205) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2206) reg_val |= BIT(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2207) if (__alps_command_mode_write_reg(psmouse, reg_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2208) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2211) if (alps_exit_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2212) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2214) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2217) static int alps_hw_init_v3(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2219) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2220) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2221) int reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2222) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2224) if ((priv->flags & ALPS_DUALPOINT) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2225) alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2226) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2228) if (alps_enter_command_mode(psmouse) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2229) alps_absolute_mode_v3(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2230) psmouse_err(psmouse, "Failed to enter absolute mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2231) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2234) reg_val = alps_command_mode_read_reg(psmouse, 0x0006);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2235) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2236) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2237) if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2238) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2240) reg_val = alps_command_mode_read_reg(psmouse, 0x0007);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2241) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2242) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2243) if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2244) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2246) if (alps_command_mode_read_reg(psmouse, 0x0144) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2247) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2248) if (__alps_command_mode_write_reg(psmouse, 0x04))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2249) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2251) if (alps_command_mode_read_reg(psmouse, 0x0159) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2252) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2253) if (__alps_command_mode_write_reg(psmouse, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2254) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2256) if (alps_command_mode_read_reg(psmouse, 0x0163) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2257) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2258) if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2259) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2261) if (alps_command_mode_read_reg(psmouse, 0x0162) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2262) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2263) if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2264) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2266) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2268) /* Set rate and enable data reporting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2269) param[0] = 0x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2270) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2271) ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2272) psmouse_err(psmouse, "Failed to enable data reporting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2273) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2276) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2278) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2279) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2280) * Leaving the touchpad in command mode will essentially render
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2281) * it unusable until the machine reboots, so exit it here just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2282) * to be safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2283) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2284) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2285) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2288) static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2290) int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2291) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2293) reg = alps_command_mode_read_reg(psmouse, reg_pitch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2294) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2295) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2297) x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2298) x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2300) y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2301) y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2303) reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2304) if (reg < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2305) return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2307) x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2308) x_electrode = 17 + x_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2310) y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2311) y_electrode = 13 + y_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2313) x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2314) y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2316) priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2317) priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2319) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2320) "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2321) x_pitch, y_pitch, x_electrode, y_electrode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2322) x_phys / 10, y_phys / 10, priv->x_res, priv->y_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2324) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2327) static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2329) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2330) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2331) int reg_val, ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2333) if (priv->flags & ALPS_DUALPOINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2334) reg_val = alps_setup_trackstick_v3(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2335) ALPS_REG_BASE_RUSHMORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2336) if (reg_val == -EIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2337) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2340) if (alps_enter_command_mode(psmouse) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2341) alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2342) alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2343) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2345) if (alps_get_v3_v7_resolution(psmouse, 0xc2da))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2346) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2348) reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2349) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2350) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2351) if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2352) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2354) if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2355) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2357) /* enter absolute mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2358) reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2359) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2360) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2361) if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2362) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2364) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2365) return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2367) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2368) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2369) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2372) /* Must be in command mode when calling this function */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2373) static int alps_absolute_mode_v4(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2375) int reg_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2377) reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2378) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2379) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2381) reg_val |= 0x02;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2382) if (__alps_command_mode_write_reg(psmouse, reg_val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2383) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2385) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2388) static int alps_hw_init_v4(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2390) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2391) unsigned char param[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2393) if (alps_enter_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2394) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2396) if (alps_absolute_mode_v4(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2397) psmouse_err(psmouse, "Failed to enter absolute mode\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2398) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2401) if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2402) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2404) if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2405) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2407) if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2408) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2410) if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2411) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2413) if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2414) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2416) if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2417) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2419) if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2420) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2422) if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2423) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2425) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2427) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2428) * This sequence changes the output from a 9-byte to an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2429) * 8-byte format. All the same data seems to be present,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2430) * just in a more compact format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2432) param[0] = 0xc8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2433) param[1] = 0x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2434) param[2] = 0x50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2435) if (ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2436) ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2437) ps2_command(ps2dev, ¶m[2], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2438) ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2439) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2441) /* Set rate and enable data reporting */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2442) param[0] = 0x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2443) if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2444) ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2445) psmouse_err(psmouse, "Failed to enable data reporting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2446) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2449) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2451) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2452) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2453) * Leaving the touchpad in command mode will essentially render
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2454) * it unusable until the machine reboots, so exit it here just
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2455) * to be safe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2456) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2457) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2458) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2461) static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2462) unsigned char index, unsigned char otp[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2463) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2464) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2466) switch (index) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2467) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2468) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2469) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2470) ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2471) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2473) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2475) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2476) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2477) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2478) ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2479) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2481) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2484) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2487) static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2488) struct alps_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2489) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2490) int num_x_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2491) int num_y_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2492) int x_pitch, y_pitch, x_phys, y_phys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2494) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2495) num_x_electrode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2496) SS4PLUS_NUMSENSOR_XOFFSET + (otp[0][2] & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2497) num_y_electrode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2498) SS4PLUS_NUMSENSOR_YOFFSET + ((otp[0][2] >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2500) priv->x_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2501) (num_x_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2502) priv->y_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2503) (num_y_electrode - 1) * SS4PLUS_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2505) x_pitch = (otp[0][1] & 0x0F) + SS4PLUS_MIN_PITCH_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2506) y_pitch = ((otp[0][1] >> 4) & 0x0F) + SS4PLUS_MIN_PITCH_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2508) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2509) num_x_electrode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2510) SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2511) num_y_electrode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2512) SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2514) priv->x_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2515) (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2516) priv->y_max =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2517) (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2519) x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2520) y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2523) x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2524) y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2526) priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2527) priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2529) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2530) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2532) static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2533) struct alps_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2535) unsigned char is_btnless;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2537) if (IS_SS4PLUS_DEV(priv->dev_id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2538) is_btnless = (otp[1][0] >> 1) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2539) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2540) is_btnless = (otp[1][1] >> 3) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2542) if (is_btnless)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2543) priv->flags |= ALPS_BUTTONPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2545) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2548) static int alps_update_dual_info_ss4_v2(unsigned char otp[][4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2549) struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2550) struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2551) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2552) bool is_dual = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2553) int reg_val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2554) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2556) if (IS_SS4PLUS_DEV(priv->dev_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2557) is_dual = (otp[0][0] >> 4) & 0x01;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2559) if (!is_dual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2560) /* For support TrackStick of Thinkpad L/E series */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2561) if (alps_exit_command_mode(psmouse) == 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2562) alps_enter_command_mode(psmouse) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2563) reg_val = alps_command_mode_read_reg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2564) 0xD7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2566) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2567) ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2569) if (reg_val == 0x0C || reg_val == 0x1D)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2570) is_dual = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2574) if (is_dual)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2575) priv->flags |= ALPS_DUALPOINT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2576) ALPS_DUALPOINT_WITH_PRESSURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2578) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2581) static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2582) struct alps_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2584) unsigned char otp[2][4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2586) memset(otp, 0, sizeof(otp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2588) if (alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2589) alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2590) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2592) alps_update_device_area_ss4_v2(otp, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2594) alps_update_btn_info_ss4_v2(otp, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2596) alps_update_dual_info_ss4_v2(otp, priv, psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2598) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2601) static int alps_dolphin_get_device_area(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2602) struct alps_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2603) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2604) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2605) unsigned char param[4] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2606) int num_x_electrode, num_y_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2608) if (alps_enter_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2609) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2611) param[0] = 0x0a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2612) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2613) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2614) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2615) ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2616) ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2617) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2619) if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2620) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2623) * Dolphin's sensor line number is not fixed. It can be calculated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2624) * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2625) * Further more, we can get device's x_max and y_max by multiplying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2626) * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2627) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2628) * e.g. When we get register's sensor_x = 11 & sensor_y = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2629) * real sensor line number X = 11 + 8 = 19, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2630) * real sensor line number Y = 8 + 1 = 9.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2631) * So, x_max = (19 - 1) * 64 = 1152, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2632) * y_max = (9 - 1) * 64 = 512.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2633) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2634) num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2635) num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2636) priv->x_bits = num_x_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2637) priv->y_bits = num_y_electrode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2638) priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2639) priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2641) if (alps_exit_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2642) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2644) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2647) static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2649) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2650) unsigned char param[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2652) /* This is dolphin "v1" as empirically defined by florin9doi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2653) param[0] = 0x64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2654) param[1] = 0x28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2656) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2657) ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2658) ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2659) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2664) static int alps_hw_init_v7(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2666) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2667) int reg_val, ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2669) if (alps_enter_command_mode(psmouse) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2670) alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2671) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2673) if (alps_get_v3_v7_resolution(psmouse, 0xc397))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2674) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2676) if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2677) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2679) reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2680) if (reg_val == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2681) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2682) if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2683) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2685) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2686) return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2688) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2689) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2690) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2693) static int alps_hw_init_ss4_v2(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2695) struct ps2dev *ps2dev = &psmouse->ps2dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2696) char param[2] = {0x64, 0x28};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2697) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2699) /* enter absolute mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2700) if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2701) ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2702) ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2703) ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2704) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2705) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2707) /* T.B.D. Decread noise packet number, delete in the future */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2708) if (alps_exit_command_mode(psmouse) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2709) alps_enter_command_mode(psmouse) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2710) alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2711) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2713) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2715) return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2717) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2718) alps_exit_command_mode(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2719) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2722) static int alps_set_protocol(struct psmouse *psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2723) struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2724) const struct alps_protocol_info *protocol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2725) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2726) psmouse->private = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2728) timer_setup(&priv->timer, alps_flush_packet, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2730) priv->proto_version = protocol->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2731) priv->byte0 = protocol->byte0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2732) priv->mask0 = protocol->mask0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2733) priv->flags = protocol->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2734)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2735) priv->x_max = 2000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2736) priv->y_max = 1400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2737) priv->x_bits = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2738) priv->y_bits = 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2740) switch (priv->proto_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2741) case ALPS_PROTO_V1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2742) case ALPS_PROTO_V2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2743) priv->hw_init = alps_hw_init_v1_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2744) priv->process_packet = alps_process_packet_v1_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2745) priv->set_abs_params = alps_set_abs_params_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2746) priv->x_max = 1023;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2747) priv->y_max = 767;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2748) if (dmi_check_system(alps_dmi_has_separate_stick_buttons))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2749) priv->flags |= ALPS_STICK_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2750) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2752) case ALPS_PROTO_V3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2753) priv->hw_init = alps_hw_init_v3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2754) priv->process_packet = alps_process_packet_v3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2755) priv->set_abs_params = alps_set_abs_params_semi_mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2756) priv->decode_fields = alps_decode_pinnacle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2757) priv->nibble_commands = alps_v3_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2758) priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2760) if (alps_probe_trackstick_v3_v7(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2761) ALPS_REG_BASE_PINNACLE) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2762) priv->flags &= ~ALPS_DUALPOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2764) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2766) case ALPS_PROTO_V3_RUSHMORE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2767) priv->hw_init = alps_hw_init_rushmore_v3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2768) priv->process_packet = alps_process_packet_v3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2769) priv->set_abs_params = alps_set_abs_params_semi_mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2770) priv->decode_fields = alps_decode_rushmore;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2771) priv->nibble_commands = alps_v3_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2772) priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2773) priv->x_bits = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2774) priv->y_bits = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2776) if (alps_probe_trackstick_v3_v7(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2777) ALPS_REG_BASE_RUSHMORE) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2778) priv->flags &= ~ALPS_DUALPOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2780) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2782) case ALPS_PROTO_V4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2783) priv->hw_init = alps_hw_init_v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2784) priv->process_packet = alps_process_packet_v4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2785) priv->set_abs_params = alps_set_abs_params_semi_mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2786) priv->nibble_commands = alps_v4_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2787) priv->addr_command = PSMOUSE_CMD_DISABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2788) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2790) case ALPS_PROTO_V5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2791) priv->hw_init = alps_hw_init_dolphin_v1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2792) priv->process_packet = alps_process_touchpad_packet_v3_v5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2793) priv->decode_fields = alps_decode_dolphin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2794) priv->set_abs_params = alps_set_abs_params_semi_mt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2795) priv->nibble_commands = alps_v3_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2796) priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2797) priv->x_bits = 23;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2798) priv->y_bits = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2799)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2800) if (alps_dolphin_get_device_area(psmouse, priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2801) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2803) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2805) case ALPS_PROTO_V6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2806) priv->hw_init = alps_hw_init_v6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2807) priv->process_packet = alps_process_packet_v6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2808) priv->set_abs_params = alps_set_abs_params_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2809) priv->nibble_commands = alps_v6_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2810) priv->x_max = 2047;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2811) priv->y_max = 1535;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2812) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2814) case ALPS_PROTO_V7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2815) priv->hw_init = alps_hw_init_v7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2816) priv->process_packet = alps_process_packet_v7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2817) priv->decode_fields = alps_decode_packet_v7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2818) priv->set_abs_params = alps_set_abs_params_v7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2819) priv->nibble_commands = alps_v3_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2820) priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2821) priv->x_max = 0xfff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2822) priv->y_max = 0x7ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2824) if (priv->fw_ver[1] != 0xba)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2825) priv->flags |= ALPS_BUTTONPAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2827) if (alps_probe_trackstick_v3_v7(psmouse, ALPS_REG_BASE_V7) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2828) priv->flags &= ~ALPS_DUALPOINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2830) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2831)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2832) case ALPS_PROTO_V8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2833) priv->hw_init = alps_hw_init_ss4_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2834) priv->process_packet = alps_process_packet_ss4_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2835) priv->decode_fields = alps_decode_ss4_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2836) priv->set_abs_params = alps_set_abs_params_ss4_v2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2837) priv->nibble_commands = alps_v3_nibble_commands;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2838) priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2840) if (alps_set_defaults_ss4_v2(psmouse, priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2841) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2843) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2844) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2846) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2847) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2849) static const struct alps_protocol_info *alps_match_table(unsigned char *e7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2850) unsigned char *ec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2851) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2852) const struct alps_model_info *model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2853) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2855) for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2856) model = &alps_model_data[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2858) if (!memcmp(e7, model->signature, sizeof(model->signature)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2859) return &model->protocol_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2862) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2865) static bool alps_is_cs19_trackpoint(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2867) u8 param[2] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2869) if (ps2_command(&psmouse->ps2dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2870) param, MAKE_PS2_CMD(0, 2, TP_READ_ID)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2871) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2873) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2874) * param[0] contains the trackpoint device variant_id while
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2875) * param[1] contains the firmware_id. So far all alps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2876) * trackpoint-only devices have their variant_ids equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2877) * TP_VARIANT_ALPS and their firmware_ids are in 0x20~0x2f range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2878) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2879) return param[0] == TP_VARIANT_ALPS && ((param[1] & 0xf0) == 0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2882) static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2884) const struct alps_protocol_info *protocol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2885) unsigned char e6[4], e7[4], ec[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2886) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2888) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2889) * First try "E6 report".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2890) * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2891) * The bits 0-2 of the first byte will be 1s if some buttons are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2892) * pressed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2894) if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2895) PSMOUSE_CMD_SETSCALE11, e6))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2896) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2898) if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2899) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2902) * Now get the "E7" and "EC" reports. These will uniquely identify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2903) * most ALPS touchpads.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2904) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2905) if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2906) PSMOUSE_CMD_SETSCALE21, e7) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2907) alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2908) PSMOUSE_CMD_RESET_WRAP, ec) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2909) alps_exit_command_mode(psmouse))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2910) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2912) protocol = alps_match_table(e7, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2913) if (!protocol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2914) if (e7[0] == 0x73 && e7[1] == 0x02 && e7[2] == 0x64 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2915) ec[2] == 0x8a) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2916) protocol = &alps_v4_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2917) } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2918) ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2919) protocol = &alps_v5_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2920) } else if (ec[0] == 0x88 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2921) ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2922) protocol = &alps_v7_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2923) } else if (ec[0] == 0x88 && ec[1] == 0x08) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2924) protocol = &alps_v3_rushmore_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2925) } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2926) ec[2] >= 0x90 && ec[2] <= 0x9d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2927) protocol = &alps_v3_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2928) } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2929) (e7[2] == 0x14 || e7[2] == 0x28)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2930) protocol = &alps_v8_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2931) } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0xc8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2932) protocol = &alps_v9_protocol_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2933) psmouse_warn(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2934) "Unsupported ALPS V9 touchpad: E7=%3ph, EC=%3ph\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2935) e7, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2936) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2937) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2938) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2939) "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2940) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2941) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2944) if (priv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2945) /* Save Device ID and Firmware version */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2946) memcpy(priv->dev_id, e7, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2947) memcpy(priv->fw_ver, ec, 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2948) error = alps_set_protocol(psmouse, priv, protocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2949) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2950) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2953) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2956) static int alps_reconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2957) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2958) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2960) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2961)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2962) if (alps_identify(psmouse, priv) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2963) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2965) return priv->hw_init(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2968) static void alps_disconnect(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2969) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2970) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2972) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2973) del_timer_sync(&priv->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2974) if (priv->dev2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2975) input_unregister_device(priv->dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2976) if (!IS_ERR_OR_NULL(priv->dev3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2977) input_unregister_device(priv->dev3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2978) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2981) static void alps_set_abs_params_st(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2982) struct input_dev *dev1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2983) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2984) input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2985) input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2986) input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2989) static void alps_set_abs_params_mt_common(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2990) struct input_dev *dev1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2991) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2992) input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2993) input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2995) input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2996) input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2998) set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2999) set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3002) static void alps_set_abs_params_semi_mt(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3003) struct input_dev *dev1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3004) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3005) alps_set_abs_params_mt_common(priv, dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3006) input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3008) input_mt_init_slots(dev1, MAX_TOUCHES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3009) INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3010) INPUT_MT_SEMI_MT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3013) static void alps_set_abs_params_v7(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3014) struct input_dev *dev1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3016) alps_set_abs_params_mt_common(priv, dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3017) set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3019) input_mt_init_slots(dev1, MAX_TOUCHES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3020) INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3021) INPUT_MT_TRACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3023) set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3026) static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3027) struct input_dev *dev1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3028) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3029) alps_set_abs_params_mt_common(priv, dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3030) input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3031) set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3033) input_mt_init_slots(dev1, MAX_TOUCHES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3034) INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3035) INPUT_MT_TRACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3038) int alps_init(struct psmouse *psmouse)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3039) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3040) struct alps_data *priv = psmouse->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3041) struct input_dev *dev1 = psmouse->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3042) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3044) error = priv->hw_init(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3045) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3046) goto init_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3048) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3049) * Undo part of setup done for us by psmouse core since touchpad
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3050) * is not a relative device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3051) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3052) __clear_bit(EV_REL, dev1->evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3053) __clear_bit(REL_X, dev1->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3054) __clear_bit(REL_Y, dev1->relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3056) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3057) * Now set up our capabilities.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3058) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3059) dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3060) dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3061) dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3062) dev1->keybit[BIT_WORD(BTN_LEFT)] |=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3063) BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3065) dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3066)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3067) priv->set_abs_params(priv, dev1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3069) if (priv->flags & ALPS_WHEEL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3070) dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3071) dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3072) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3074) if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3075) dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3076) dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3079) if (priv->flags & ALPS_FOUR_BUTTONS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3080) dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3081) dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3082) dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3083) dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3084) } else if (priv->flags & ALPS_BUTTONPAD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3085) set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3086) clear_bit(BTN_RIGHT, dev1->keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3087) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3088) dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3090)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3091) if (priv->flags & ALPS_DUALPOINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3092) struct input_dev *dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3093)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3094) dev2 = input_allocate_device();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3095) if (!dev2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3096) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3097) "failed to allocate trackstick device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3098) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3099) goto init_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3102) snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3103) psmouse->ps2dev.serio->phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3104) dev2->phys = priv->phys2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3106) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3107) * format of input device name is: "protocol vendor name"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3108) * see function psmouse_switch_protocol() in psmouse-base.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3109) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3110) dev2->name = "AlpsPS/2 ALPS DualPoint Stick";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3112) dev2->id.bustype = BUS_I8042;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3113) dev2->id.vendor = 0x0002;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3114) dev2->id.product = PSMOUSE_ALPS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3115) dev2->id.version = priv->proto_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3116) dev2->dev.parent = &psmouse->ps2dev.serio->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3118) input_set_capability(dev2, EV_REL, REL_X);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3119) input_set_capability(dev2, EV_REL, REL_Y);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3120) if (priv->flags & ALPS_DUALPOINT_WITH_PRESSURE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3121) input_set_capability(dev2, EV_ABS, ABS_PRESSURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3122) input_set_abs_params(dev2, ABS_PRESSURE, 0, 127, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3124) input_set_capability(dev2, EV_KEY, BTN_LEFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3125) input_set_capability(dev2, EV_KEY, BTN_RIGHT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3126) input_set_capability(dev2, EV_KEY, BTN_MIDDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3128) __set_bit(INPUT_PROP_POINTER, dev2->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3129) __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3131) error = input_register_device(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3132) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3133) psmouse_err(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3134) "failed to register trackstick device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3135) error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3136) input_free_device(dev2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3137) goto init_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3140) priv->dev2 = dev2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3143) priv->psmouse = psmouse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3145) INIT_DELAYED_WORK(&priv->dev3_register_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3146) alps_register_bare_ps2_mouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3148) psmouse->protocol_handler = alps_process_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3149) psmouse->poll = alps_poll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3150) psmouse->disconnect = alps_disconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3151) psmouse->reconnect = alps_reconnect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3152) psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3154) /* We are having trouble resyncing ALPS touchpads so disable it for now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3155) psmouse->resync_time = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3157) /* Allow 2 invalid packets without resetting device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3158) psmouse->resetafter = psmouse->pktsize * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3160) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3162) init_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3163) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3164) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3165) * Even though we did not allocate psmouse->private we do free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3166) * it here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3168) kfree(psmouse->private);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3169) psmouse->private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3170) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3173) int alps_detect(struct psmouse *psmouse, bool set_properties)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3175) struct alps_data *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3176) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3178) error = alps_identify(psmouse, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3179) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3180) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3183) * ALPS cs19 is a trackpoint-only device, and uses different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3184) * protocol than DualPoint ones, so we return -EINVAL here and let
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3185) * trackpoint.c drive this device. If the trackpoint driver is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3186) * enabled, the device will fall back to a bare PS/2 mouse.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3187) * If ps2_command() fails here, we depend on the immediately
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3188) * followed psmouse_reset() to reset the device to normal state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3190) if (alps_is_cs19_trackpoint(psmouse)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3191) psmouse_dbg(psmouse,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3192) "ALPS CS19 trackpoint-only device detected, ignoring\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3193) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3197) * Reset the device to make sure it is fully operational:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3198) * on some laptops, like certain Dell Latitudes, we may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3199) * fail to properly detect presence of trackstick if device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3200) * has not been reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3202) psmouse_reset(psmouse);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3204) priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3205) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3206) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3208) error = alps_identify(psmouse, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3209) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3210) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3211) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3214) if (set_properties) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3215) psmouse->vendor = "ALPS";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3216) psmouse->name = priv->flags & ALPS_DUALPOINT ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3217) "DualPoint TouchPad" : "GlidePoint";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3218) psmouse->model = priv->proto_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3219) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3221) * Destroy alps_data structure we allocated earlier since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3222) * this was just a "trial run". Otherwise we'll keep it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3223) * to be used by alps_init() which has to be called if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3224) * we succeed and set_properties is true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3226) kfree(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3227) psmouse->private = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3232)