blob: 220acb63ffd7dfbb38f5fee51a186ebf9c201372 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * ALPS touchpad PS/2 mouse driver
3 *
4 * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
Peter Osterlund963f6262005-07-11 01:08:04 -05005 * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
7 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08008 * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
10 * ALPS detection, tap switching and status querying info is taken from
11 * tpconfig utility (by C. Scott Ananian and Bruce Kall).
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License version 2 as published by
15 * the Free Software Foundation.
16 */
17
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <linux/input.h>
Seth Forshee01ce6612011-11-07 19:54:13 -080020#include <linux/input/mt.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/serio.h>
22#include <linux/libps2.h>
23
24#include "psmouse.h"
25#include "alps.h"
26
Seth Forshee25bded72011-11-07 19:53:36 -080027/*
28 * Definitions for ALPS version 3 and 4 command mode protocol
29 */
30#define ALPS_CMD_NIBBLE_10 0x01f2
31
Kevin Cernekeecd401202013-02-13 22:28:07 -080032#define ALPS_REG_BASE_RUSHMORE 0xc2c0
33#define ALPS_REG_BASE_PINNACLE 0x0000
34
Seth Forshee25bded72011-11-07 19:53:36 -080035static const struct alps_nibble_commands alps_v3_nibble_commands[] = {
36 { PSMOUSE_CMD_SETPOLL, 0x00 }, /* 0 */
37 { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
38 { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
39 { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
40 { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
41 { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
42 { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
43 { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
44 { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
45 { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
46 { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
47 { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
48 { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
49 { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
50 { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
51 { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
52};
53
54static const struct alps_nibble_commands alps_v4_nibble_commands[] = {
55 { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
56 { PSMOUSE_CMD_RESET_DIS, 0x00 }, /* 1 */
57 { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* 2 */
58 { PSMOUSE_CMD_SETRATE, 0x0a }, /* 3 */
59 { PSMOUSE_CMD_SETRATE, 0x14 }, /* 4 */
60 { PSMOUSE_CMD_SETRATE, 0x28 }, /* 5 */
61 { PSMOUSE_CMD_SETRATE, 0x3c }, /* 6 */
62 { PSMOUSE_CMD_SETRATE, 0x50 }, /* 7 */
63 { PSMOUSE_CMD_SETRATE, 0x64 }, /* 8 */
64 { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 9 */
65 { ALPS_CMD_NIBBLE_10, 0x00 }, /* a */
66 { PSMOUSE_CMD_SETRES, 0x00 }, /* b */
67 { PSMOUSE_CMD_SETRES, 0x01 }, /* c */
68 { PSMOUSE_CMD_SETRES, 0x02 }, /* d */
69 { PSMOUSE_CMD_SETRES, 0x03 }, /* e */
70 { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
71};
72
Yunkang Tang95f75e92013-12-01 22:33:52 -080073static const struct alps_nibble_commands alps_v6_nibble_commands[] = {
74 { PSMOUSE_CMD_ENABLE, 0x00 }, /* 0 */
75 { PSMOUSE_CMD_SETRATE, 0x0a }, /* 1 */
76 { PSMOUSE_CMD_SETRATE, 0x14 }, /* 2 */
77 { PSMOUSE_CMD_SETRATE, 0x28 }, /* 3 */
78 { PSMOUSE_CMD_SETRATE, 0x3c }, /* 4 */
79 { PSMOUSE_CMD_SETRATE, 0x50 }, /* 5 */
80 { PSMOUSE_CMD_SETRATE, 0x64 }, /* 6 */
81 { PSMOUSE_CMD_SETRATE, 0xc8 }, /* 7 */
82 { PSMOUSE_CMD_GETID, 0x00 }, /* 8 */
83 { PSMOUSE_CMD_GETINFO, 0x00 }, /* 9 */
84 { PSMOUSE_CMD_SETRES, 0x00 }, /* a */
85 { PSMOUSE_CMD_SETRES, 0x01 }, /* b */
86 { PSMOUSE_CMD_SETRES, 0x02 }, /* c */
87 { PSMOUSE_CMD_SETRES, 0x03 }, /* d */
88 { PSMOUSE_CMD_SETSCALE21, 0x00 }, /* e */
89 { PSMOUSE_CMD_SETSCALE11, 0x00 }, /* f */
90};
91
Seth Forshee25bded72011-11-07 19:53:36 -080092
Maxim Levitsky71bb21b2009-11-16 22:12:22 -080093#define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */
94#define ALPS_PASS 0x04 /* device has a pass-through port */
95
96#define ALPS_WHEEL 0x08 /* hardware wheel present */
97#define ALPS_FW_BK_1 0x10 /* front & back buttons present */
98#define ALPS_FW_BK_2 0x20 /* front & back buttons present */
99#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800100#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
101 6-byte ALPS packet */
Yunkang Tang38088432014-07-26 13:51:41 -0700102#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Helge Dellere38de672006-09-10 21:54:39 -0400104static const struct alps_model_info alps_model_data[] = {
Dmitry Torokhov8326bb52015-01-13 21:08:00 -0800105 { { 0x32, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Toshiba Salellite Pro M10 */
106 { { 0x33, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V1, 0x88, 0xf8, 0 } }, /* UMAX-530T */
107 { { 0x53, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
108 { { 0x53, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
109 { { 0x60, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } }, /* HP ze1115 */
110 { { 0x63, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
111 { { 0x63, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
112 { { 0x63, 0x02, 0x28 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Fujitsu Siemens S6010 */
113 { { 0x63, 0x02, 0x3c }, 0x00, { ALPS_PROTO_V2, 0x8f, 0x8f, ALPS_WHEEL } }, /* Toshiba Satellite S2400-103 */
114 { { 0x63, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xef, 0xef, ALPS_FW_BK_1 } }, /* NEC Versa L320 */
115 { { 0x63, 0x02, 0x64 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
116 { { 0x63, 0x03, 0xc8 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D800 */
117 { { 0x73, 0x00, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_DUALPOINT } }, /* ThinkPad R61 8918-5QG */
118 { { 0x73, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, 0 } },
119 { { 0x73, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_FW_BK_2 } }, /* Ahtec Laptop */
Dmitry Torokhov626b9da2015-02-15 15:55:16 -0800120
121 /*
122 * XXX This entry is suspicious. First byte has zero lower nibble,
123 * which is what a normal mouse would report. Also, the value 0x0e
124 * isn't valid per PS/2 spec.
125 */
126 { { 0x20, 0x02, 0x0e }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
127
Dmitry Torokhov8326bb52015-01-13 21:08:00 -0800128 { { 0x22, 0x02, 0x0a }, 0x00, { ALPS_PROTO_V2, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT } },
129 { { 0x22, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT } }, /* Dell Latitude D600 */
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800130 /* Dell Latitude E5500, E6400, E6500, Precision M4400 */
Dmitry Torokhov8326bb52015-01-13 21:08:00 -0800131 { { 0x62, 0x02, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf,
132 ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } },
133 { { 0x73, 0x00, 0x14 }, 0x00, { ALPS_PROTO_V6, 0xff, 0xff, ALPS_DUALPOINT } }, /* Dell XT2 */
134 { { 0x73, 0x02, 0x50 }, 0x00, { ALPS_PROTO_V2, 0xcf, 0xcf, ALPS_FOUR_BUTTONS } }, /* Dell Vostro 1400 */
135 { { 0x52, 0x01, 0x14 }, 0x00, { ALPS_PROTO_V2, 0xff, 0xff,
136 ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED } }, /* Toshiba Tecra A11-11L */
137 { { 0x73, 0x02, 0x64 }, 0x8a, { ALPS_PROTO_V4, 0x8f, 0x8f, 0 } },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138};
139
Dmitry Torokhov3296f712015-01-12 00:30:32 -0800140static const struct alps_protocol_info alps_v3_protocol_data = {
141 ALPS_PROTO_V3, 0x8f, 0x8f, ALPS_DUALPOINT
142};
143
144static const struct alps_protocol_info alps_v3_rushmore_data = {
145 ALPS_PROTO_V3_RUSHMORE, 0x8f, 0x8f, ALPS_DUALPOINT
146};
147
148static const struct alps_protocol_info alps_v5_protocol_data = {
149 ALPS_PROTO_V5, 0xc8, 0xd8, 0
150};
151
152static const struct alps_protocol_info alps_v7_protocol_data = {
153 ALPS_PROTO_V7, 0x48, 0x48, ALPS_DUALPOINT
154};
155
Masaki Ota3db5b9f2015-03-27 20:57:52 -0700156static const struct alps_protocol_info alps_v8_protocol_data = {
157 ALPS_PROTO_V8, 0x18, 0x18, 0
158};
159
Kevin Cernekee24af5cb2013-02-13 22:22:08 -0800160static void alps_set_abs_params_st(struct alps_data *priv,
161 struct input_dev *dev1);
162static void alps_set_abs_params_mt(struct alps_data *priv,
163 struct input_dev *dev1);
Masaki Ota8eccd392015-03-27 20:44:21 -0700164static void alps_set_abs_params_v7(struct alps_data *priv,
165 struct input_dev *dev1);
Masaki Ota3db5b9f2015-03-27 20:57:52 -0700166static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
167 struct input_dev *dev1);
Kevin Cernekee24af5cb2013-02-13 22:22:08 -0800168
Seth Forsheed4b347b2011-11-07 19:53:15 -0800169/* Packet formats are described in Documentation/input/alps.txt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800171static bool alps_is_valid_first_byte(struct alps_data *priv,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800172 unsigned char data)
173{
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800174 return (data & priv->mask0) == priv->byte0;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800175}
176
Pali Rohár04aae282015-01-14 13:18:30 -0800177static void alps_report_buttons(struct input_dev *dev1, struct input_dev *dev2,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800178 int left, int right, int middle)
179{
Martin Buckc91ed052010-03-13 22:23:58 -0800180 struct input_dev *dev;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800181
Martin Buckc91ed052010-03-13 22:23:58 -0800182 /*
183 * If shared button has already been reported on the
184 * other device (dev2) then this event should be also
185 * sent through that device.
186 */
Pali Rohár04aae282015-01-14 13:18:30 -0800187 dev = (dev2 && test_bit(BTN_LEFT, dev2->key)) ? dev2 : dev1;
Martin Buckc91ed052010-03-13 22:23:58 -0800188 input_report_key(dev, BTN_LEFT, left);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800189
Pali Rohár04aae282015-01-14 13:18:30 -0800190 dev = (dev2 && test_bit(BTN_RIGHT, dev2->key)) ? dev2 : dev1;
Martin Buckc91ed052010-03-13 22:23:58 -0800191 input_report_key(dev, BTN_RIGHT, right);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800192
Pali Rohár04aae282015-01-14 13:18:30 -0800193 dev = (dev2 && test_bit(BTN_MIDDLE, dev2->key)) ? dev2 : dev1;
Martin Buckc91ed052010-03-13 22:23:58 -0800194 input_report_key(dev, BTN_MIDDLE, middle);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800195
Martin Buckc91ed052010-03-13 22:23:58 -0800196 /*
197 * Sync the _other_ device now, we'll do the first
198 * device later once we report the rest of the events.
199 */
Pali Rohár04aae282015-01-14 13:18:30 -0800200 if (dev2)
201 input_sync(dev2);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -0800202}
203
Seth Forshee25bded72011-11-07 19:53:36 -0800204static void alps_process_packet_v1_v2(struct psmouse *psmouse)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205{
206 struct alps_data *priv = psmouse->private;
207 unsigned char *packet = psmouse->packet;
Dmitry Torokhov2e5b6362005-09-15 02:01:44 -0500208 struct input_dev *dev = psmouse->dev;
209 struct input_dev *dev2 = priv->dev2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 int x, y, z, ges, fin, left, right, middle;
Ivan Casado Ruizc30b4c12005-06-01 02:39:18 -0500211 int back = 0, forward = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800213 if (priv->proto_version == ALPS_PROTO_V1) {
Yotam Medinid2f40122006-05-29 23:30:36 -0400214 left = packet[2] & 0x10;
215 right = packet[2] & 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 middle = 0;
217 x = packet[1] | ((packet[0] & 0x07) << 7);
218 y = packet[4] | ((packet[3] & 0x07) << 7);
219 z = packet[5];
220 } else {
221 left = packet[3] & 1;
222 right = packet[3] & 2;
223 middle = packet[3] & 4;
224 x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
225 y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
226 z = packet[5];
227 }
228
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800229 if (priv->flags & ALPS_FW_BK_1) {
Laszlo Kajan3c00bb92008-03-18 00:39:55 -0400230 back = packet[0] & 0x10;
231 forward = packet[2] & 4;
Ivan Casado Ruizc30b4c12005-06-01 02:39:18 -0500232 }
233
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800234 if (priv->flags & ALPS_FW_BK_2) {
Ivan Casado Ruizc30b4c12005-06-01 02:39:18 -0500235 back = packet[3] & 4;
236 forward = packet[2] & 4;
237 if ((middle = forward && back))
238 forward = back = 0;
239 }
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 ges = packet[2] & 1;
242 fin = packet[2] & 2;
243
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800244 if ((priv->flags & ALPS_DUALPOINT) && z == 127) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x));
246 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
Ulrich Dangeld7ed5d82009-06-11 00:15:09 -0700247
Pali Rohár04aae282015-01-14 13:18:30 -0800248 alps_report_buttons(dev2, dev, left, right, middle);
Ulrich Dangeld7ed5d82009-06-11 00:15:09 -0700249
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 input_sync(dev2);
251 return;
252 }
253
Pali Rohár04aae282015-01-14 13:18:30 -0800254 alps_report_buttons(dev, dev2, left, right, middle);
Ulrich Dangeld7ed5d82009-06-11 00:15:09 -0700255
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 /* Convert hardware tap to a reasonable Z value */
Maxim Levitsky71bb21b2009-11-16 22:12:22 -0800257 if (ges && !fin)
258 z = 40;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 /*
261 * A "tap and drag" operation is reported by the hardware as a transition
262 * from (!fin && ges) to (fin && ges). This should be translated to the
263 * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
264 */
265 if (ges && fin && !priv->prev_fin) {
266 input_report_abs(dev, ABS_X, x);
267 input_report_abs(dev, ABS_Y, y);
268 input_report_abs(dev, ABS_PRESSURE, 0);
269 input_report_key(dev, BTN_TOOL_FINGER, 0);
270 input_sync(dev);
271 }
272 priv->prev_fin = fin;
273
Maxim Levitsky71bb21b2009-11-16 22:12:22 -0800274 if (z > 30)
275 input_report_key(dev, BTN_TOUCH, 1);
276 if (z < 25)
277 input_report_key(dev, BTN_TOUCH, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278
279 if (z > 0) {
280 input_report_abs(dev, ABS_X, x);
281 input_report_abs(dev, ABS_Y, y);
282 }
283
284 input_report_abs(dev, ABS_PRESSURE, z);
285 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
286
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800287 if (priv->flags & ALPS_WHEEL)
Vojtech Pavlike6c047b2005-09-04 01:40:43 -0500288 input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800290 if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
Ivan Casado Ruizc30b4c12005-06-01 02:39:18 -0500291 input_report_key(dev, BTN_FORWARD, forward);
292 input_report_key(dev, BTN_BACK, back);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 }
294
Kevin Cernekee99df65e2013-02-13 20:56:33 -0800295 if (priv->flags & ALPS_FOUR_BUTTONS) {
Maxim Levitsky71bb21b2009-11-16 22:12:22 -0800296 input_report_key(dev, BTN_0, packet[2] & 4);
297 input_report_key(dev, BTN_1, packet[0] & 0x10);
298 input_report_key(dev, BTN_2, packet[3] & 4);
299 input_report_key(dev, BTN_3, packet[0] & 0x20);
300 }
301
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 input_sync(dev);
303}
304
Seth Forshee01ce6612011-11-07 19:54:13 -0800305/*
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800306 * Process bitmap data for V5 protocols. Return value is null.
307 *
308 * The bitmaps don't have enough data to track fingers, so this function
309 * only generates points representing a bounding box of at most two contacts.
Hans de Goede02d04252014-07-25 22:43:35 -0700310 * These two points are returned in fields->mt.
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800311 */
312static void alps_process_bitmap_dolphin(struct alps_data *priv,
Hans de Goede02d04252014-07-25 22:43:35 -0700313 struct alps_fields *fields)
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800314{
315 int box_middle_x, box_middle_y;
316 unsigned int x_map, y_map;
317 unsigned char start_bit, end_bit;
318 unsigned char x_msb, x_lsb, y_msb, y_lsb;
319
320 x_map = fields->x_map;
321 y_map = fields->y_map;
322
323 if (!x_map || !y_map)
324 return;
325
326 /* Get Most-significant and Least-significant bit */
327 x_msb = fls(x_map);
328 x_lsb = ffs(x_map);
329 y_msb = fls(y_map);
330 y_lsb = ffs(y_map);
331
332 /* Most-significant bit should never exceed max sensor line number */
333 if (x_msb > priv->x_bits || y_msb > priv->y_bits)
334 return;
335
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800336 if (fields->fingers > 1) {
337 start_bit = priv->x_bits - x_msb;
338 end_bit = priv->x_bits - x_lsb;
339 box_middle_x = (priv->x_max * (start_bit + end_bit)) /
340 (2 * (priv->x_bits - 1));
341
342 start_bit = y_lsb - 1;
343 end_bit = y_msb - 1;
344 box_middle_y = (priv->y_max * (start_bit + end_bit)) /
345 (2 * (priv->y_bits - 1));
Hans de Goede02d04252014-07-25 22:43:35 -0700346 fields->mt[0] = fields->st;
347 fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x;
348 fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y;
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800349 }
350}
351
Hans de Goede036e6c72014-07-25 22:38:51 -0700352static void alps_get_bitmap_points(unsigned int map,
353 struct alps_bitmap_point *low,
354 struct alps_bitmap_point *high,
355 int *fingers)
356{
357 struct alps_bitmap_point *point;
358 int i, bit, prev_bit = 0;
359
360 point = low;
361 for (i = 0; map != 0; i++, map >>= 1) {
362 bit = map & 1;
363 if (bit) {
364 if (!prev_bit) {
365 point->start_bit = i;
Hans de Goede105affb2014-07-25 22:41:51 -0700366 point->num_bits = 0;
Hans de Goede036e6c72014-07-25 22:38:51 -0700367 (*fingers)++;
368 }
369 point->num_bits++;
370 } else {
371 if (prev_bit)
372 point = high;
Hans de Goede036e6c72014-07-25 22:38:51 -0700373 }
374 prev_bit = bit;
375 }
376}
377
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800378/*
Seth Forshee01ce6612011-11-07 19:54:13 -0800379 * Process bitmap data from v3 and v4 protocols. Returns the number of
380 * fingers detected. A return value of 0 means at least one of the
381 * bitmaps was empty.
382 *
383 * The bitmaps don't have enough data to track fingers, so this function
384 * only generates points representing a bounding box of all contacts.
Hans de Goede02d04252014-07-25 22:43:35 -0700385 * These points are returned in fields->mt when the return value
Seth Forshee01ce6612011-11-07 19:54:13 -0800386 * is greater than 0.
387 */
Kevin Cernekee7a9f73e2013-02-13 22:24:55 -0800388static int alps_process_bitmap(struct alps_data *priv,
Hans de Goede02d04252014-07-25 22:43:35 -0700389 struct alps_fields *fields)
Seth Forshee01ce6612011-11-07 19:54:13 -0800390{
Hans de Goede4dd26572015-05-20 14:41:10 -0700391 int i, fingers_x = 0, fingers_y = 0, fingers, closest;
Seth Forshee01ce6612011-11-07 19:54:13 -0800392 struct alps_bitmap_point x_low = {0,}, x_high = {0,};
393 struct alps_bitmap_point y_low = {0,}, y_high = {0,};
Hans de Goede4dd26572015-05-20 14:41:10 -0700394 struct input_mt_pos corner[4];
Seth Forshee01ce6612011-11-07 19:54:13 -0800395
Hans de Goede02d04252014-07-25 22:43:35 -0700396 if (!fields->x_map || !fields->y_map)
Seth Forshee01ce6612011-11-07 19:54:13 -0800397 return 0;
398
Hans de Goede02d04252014-07-25 22:43:35 -0700399 alps_get_bitmap_points(fields->x_map, &x_low, &x_high, &fingers_x);
400 alps_get_bitmap_points(fields->y_map, &y_low, &y_high, &fingers_y);
Seth Forshee01ce6612011-11-07 19:54:13 -0800401
402 /*
403 * Fingers can overlap, so we use the maximum count of fingers
404 * on either axis as the finger count.
405 */
406 fingers = max(fingers_x, fingers_y);
407
408 /*
Hans de Goede20bea682014-07-25 22:33:33 -0700409 * If an axis reports only a single contact, we have overlapping or
410 * adjacent fingers. Divide the single contact between the two points.
Seth Forshee01ce6612011-11-07 19:54:13 -0800411 */
Hans de Goede20bea682014-07-25 22:33:33 -0700412 if (fingers_x == 1) {
Hans de Goede28835f42014-07-25 22:42:53 -0700413 i = (x_low.num_bits - 1) / 2;
Hans de Goede20bea682014-07-25 22:33:33 -0700414 x_low.num_bits = x_low.num_bits - i;
415 x_high.start_bit = x_low.start_bit + i;
416 x_high.num_bits = max(i, 1);
417 }
418 if (fingers_y == 1) {
Hans de Goede28835f42014-07-25 22:42:53 -0700419 i = (y_low.num_bits - 1) / 2;
Hans de Goede20bea682014-07-25 22:33:33 -0700420 y_low.num_bits = y_low.num_bits - i;
421 y_high.start_bit = y_low.start_bit + i;
422 y_high.num_bits = max(i, 1);
Seth Forshee01ce6612011-11-07 19:54:13 -0800423 }
424
Hans de Goede4dd26572015-05-20 14:41:10 -0700425 /* top-left corner */
426 corner[0].x =
Hans de Goede02d04252014-07-25 22:43:35 -0700427 (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
428 (2 * (priv->x_bits - 1));
Hans de Goede4dd26572015-05-20 14:41:10 -0700429 corner[0].y =
Hans de Goede02d04252014-07-25 22:43:35 -0700430 (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
431 (2 * (priv->y_bits - 1));
Seth Forshee01ce6612011-11-07 19:54:13 -0800432
Hans de Goede4dd26572015-05-20 14:41:10 -0700433 /* top-right corner */
434 corner[1].x =
Hans de Goede02d04252014-07-25 22:43:35 -0700435 (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
436 (2 * (priv->x_bits - 1));
Hans de Goede4dd26572015-05-20 14:41:10 -0700437 corner[1].y =
438 (priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
439 (2 * (priv->y_bits - 1));
440
441 /* bottom-right corner */
442 corner[2].x =
443 (priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
444 (2 * (priv->x_bits - 1));
445 corner[2].y =
446 (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
447 (2 * (priv->y_bits - 1));
448
449 /* bottom-left corner */
450 corner[3].x =
451 (priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
452 (2 * (priv->x_bits - 1));
453 corner[3].y =
Hans de Goede02d04252014-07-25 22:43:35 -0700454 (priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
455 (2 * (priv->y_bits - 1));
Seth Forshee01ce6612011-11-07 19:54:13 -0800456
Hans de Goede40e8f532014-07-25 22:37:15 -0700457 /* y-bitmap order is reversed, except on rushmore */
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -0800458 if (priv->proto_version != ALPS_PROTO_V3_RUSHMORE) {
Hans de Goede4dd26572015-05-20 14:41:10 -0700459 for (i = 0; i < 4; i++)
460 corner[i].y = priv->y_max - corner[i].y;
Hans de Goede40e8f532014-07-25 22:37:15 -0700461 }
462
Hans de Goede4dd26572015-05-20 14:41:10 -0700463 /*
464 * We only select a corner for the second touch once per 2 finger
465 * touch sequence to avoid the chosen corner (and thus the coordinates)
466 * jumping around when the first touch is in the middle.
467 */
468 if (priv->second_touch == -1) {
469 /* Find corner closest to our st coordinates */
470 closest = 0x7fffffff;
471 for (i = 0; i < 4; i++) {
472 int dx = fields->st.x - corner[i].x;
473 int dy = fields->st.y - corner[i].y;
474 int distance = dx * dx + dy * dy;
475
476 if (distance < closest) {
477 priv->second_touch = i;
478 closest = distance;
479 }
480 }
481 /* And select the opposite corner to use for the 2nd touch */
482 priv->second_touch = (priv->second_touch + 2) % 4;
483 }
484
485 fields->mt[0] = fields->st;
486 fields->mt[1] = corner[priv->second_touch];
487
Seth Forshee01ce6612011-11-07 19:54:13 -0800488 return fingers;
489}
490
Hans de Goedecdf333e2014-07-25 22:44:42 -0700491static void alps_set_slot(struct input_dev *dev, int slot, int x, int y)
Seth Forshee01ce6612011-11-07 19:54:13 -0800492{
493 input_mt_slot(dev, slot);
Hans de Goedecdf333e2014-07-25 22:44:42 -0700494 input_mt_report_slot_state(dev, MT_TOOL_FINGER, true);
495 input_report_abs(dev, ABS_MT_POSITION_X, x);
496 input_report_abs(dev, ABS_MT_POSITION_Y, y);
Seth Forshee01ce6612011-11-07 19:54:13 -0800497}
498
Hans de Goedecdf333e2014-07-25 22:44:42 -0700499static void alps_report_mt_data(struct psmouse *psmouse, int n)
Seth Forshee01ce6612011-11-07 19:54:13 -0800500{
Hans de Goede02d04252014-07-25 22:43:35 -0700501 struct alps_data *priv = psmouse->private;
502 struct input_dev *dev = psmouse->dev;
503 struct alps_fields *f = &priv->f;
Hans de Goedecdf333e2014-07-25 22:44:42 -0700504 int i, slot[MAX_TOUCHES];
Hans de Goede02d04252014-07-25 22:43:35 -0700505
Henrik Rydberg448c7f382015-02-01 11:25:14 -0800506 input_mt_assign_slots(dev, slot, f->mt, n, 0);
Hans de Goedecdf333e2014-07-25 22:44:42 -0700507 for (i = 0; i < n; i++)
508 alps_set_slot(dev, slot[i], f->mt[i].x, f->mt[i].y);
509
510 input_mt_sync_frame(dev);
Seth Forshee01ce6612011-11-07 19:54:13 -0800511}
512
Hans de Goede68c21872014-07-25 22:47:25 -0700513static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
514{
515 struct alps_data *priv = psmouse->private;
516 struct input_dev *dev = psmouse->dev;
517 struct alps_fields *f = &priv->f;
518
519 /* Use st data when we don't have mt data */
520 if (fingers < 2) {
521 f->mt[0].x = f->st.x;
522 f->mt[0].y = f->st.y;
523 fingers = f->pressure > 0 ? 1 : 0;
Hans de Goede4dd26572015-05-20 14:41:10 -0700524 priv->second_touch = -1;
Hans de Goede68c21872014-07-25 22:47:25 -0700525 }
526
Hans de Goede99d99962014-07-25 22:48:02 -0700527 alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2);
Hans de Goede68c21872014-07-25 22:47:25 -0700528
529 input_mt_report_finger_count(dev, fingers);
530
531 input_report_key(dev, BTN_LEFT, f->left);
532 input_report_key(dev, BTN_RIGHT, f->right);
533 input_report_key(dev, BTN_MIDDLE, f->middle);
534
535 input_report_abs(dev, ABS_PRESSURE, f->pressure);
536
537 input_sync(dev);
538}
539
Seth Forshee25bded72011-11-07 19:53:36 -0800540static void alps_process_trackstick_packet_v3(struct psmouse *psmouse)
541{
542 struct alps_data *priv = psmouse->private;
543 unsigned char *packet = psmouse->packet;
544 struct input_dev *dev = priv->dev2;
545 int x, y, z, left, right, middle;
546
Pali Rohár34412ba2015-01-09 12:48:58 -0800547 /* It should be a DualPoint when received trackstick packet */
548 if (!(priv->flags & ALPS_DUALPOINT)) {
549 psmouse_warn(psmouse,
550 "Rejected trackstick packet from non DualPoint device");
551 return;
552 }
553
Seth Forshee25bded72011-11-07 19:53:36 -0800554 /* Sanity check packet */
555 if (!(packet[0] & 0x40)) {
556 psmouse_dbg(psmouse, "Bad trackstick packet, discarding\n");
557 return;
558 }
559
560 /*
561 * There's a special packet that seems to indicate the end
562 * of a stream of trackstick data. Filter these out.
563 */
564 if (packet[1] == 0x7f && packet[2] == 0x7f && packet[4] == 0x7f)
565 return;
566
567 x = (s8)(((packet[0] & 0x20) << 2) | (packet[1] & 0x7f));
568 y = (s8)(((packet[0] & 0x10) << 3) | (packet[2] & 0x7f));
569 z = (packet[4] & 0x7c) >> 2;
570
571 /*
572 * The x and y values tend to be quite large, and when used
573 * alone the trackstick is difficult to use. Scale them down
574 * to compensate.
575 */
576 x /= 8;
577 y /= 8;
578
579 input_report_rel(dev, REL_X, x);
580 input_report_rel(dev, REL_Y, -y);
581
582 /*
583 * Most ALPS models report the trackstick buttons in the touchpad
584 * packets, but a few report them here. No reliable way has been
585 * found to differentiate between the models upfront, so we enable
586 * the quirk in response to seeing a button press in the trackstick
587 * packet.
588 */
589 left = packet[3] & 0x01;
590 right = packet[3] & 0x02;
591 middle = packet[3] & 0x04;
592
593 if (!(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) &&
594 (left || right || middle))
595 priv->quirks |= ALPS_QUIRK_TRACKSTICK_BUTTONS;
596
597 if (priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS) {
598 input_report_key(dev, BTN_LEFT, left);
599 input_report_key(dev, BTN_RIGHT, right);
600 input_report_key(dev, BTN_MIDDLE, middle);
601 }
602
603 input_sync(dev);
604 return;
605}
606
Kevin Cernekeef85e5002013-02-13 22:26:11 -0800607static void alps_decode_buttons_v3(struct alps_fields *f, unsigned char *p)
608{
609 f->left = !!(p[3] & 0x01);
610 f->right = !!(p[3] & 0x02);
611 f->middle = !!(p[3] & 0x04);
612
613 f->ts_left = !!(p[3] & 0x10);
614 f->ts_right = !!(p[3] & 0x20);
615 f->ts_middle = !!(p[3] & 0x40);
616}
617
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700618static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800619 struct psmouse *psmouse)
Kevin Cernekeef85e5002013-02-13 22:26:11 -0800620{
621 f->first_mp = !!(p[4] & 0x40);
622 f->is_mp = !!(p[0] & 0x40);
623
Hans de Goedea839cd52015-05-20 14:39:21 -0700624 if (f->is_mp) {
625 f->fingers = (p[5] & 0x3) + 1;
626 f->x_map = ((p[4] & 0x7e) << 8) |
627 ((p[1] & 0x7f) << 2) |
628 ((p[0] & 0x30) >> 4);
629 f->y_map = ((p[3] & 0x70) << 4) |
630 ((p[2] & 0x7f) << 1) |
631 (p[4] & 0x01);
632 } else {
633 f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
634 ((p[0] & 0x30) >> 4);
635 f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
636 f->pressure = p[5] & 0x7f;
Kevin Cernekeef85e5002013-02-13 22:26:11 -0800637
Hans de Goedea839cd52015-05-20 14:39:21 -0700638 alps_decode_buttons_v3(f, p);
639 }
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700640
641 return 0;
Kevin Cernekeef85e5002013-02-13 22:26:11 -0800642}
643
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700644static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800645 struct psmouse *psmouse)
Kevin Cernekee1302bac2013-02-13 22:27:08 -0800646{
Hans de Goedeaab9cf72015-05-20 14:38:33 -0700647 f->first_mp = !!(p[4] & 0x40);
Yunkang Tangf105e342014-07-25 22:29:24 -0700648 f->is_mp = !!(p[5] & 0x40);
Hans de Goedeaab9cf72015-05-20 14:38:33 -0700649
Hans de Goedea839cd52015-05-20 14:39:21 -0700650 if (f->is_mp) {
651 f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
652 f->x_map = ((p[5] & 0x10) << 11) |
653 ((p[4] & 0x7e) << 8) |
654 ((p[1] & 0x7f) << 2) |
655 ((p[0] & 0x30) >> 4);
656 f->y_map = ((p[5] & 0x20) << 6) |
657 ((p[3] & 0x70) << 4) |
658 ((p[2] & 0x7f) << 1) |
659 (p[4] & 0x01);
660 } else {
661 f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
662 ((p[0] & 0x30) >> 4);
663 f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
664 f->pressure = p[5] & 0x7f;
Hans de Goedeaab9cf72015-05-20 14:38:33 -0700665
Hans de Goedea839cd52015-05-20 14:39:21 -0700666 alps_decode_buttons_v3(f, p);
667 }
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700668
669 return 0;
Kevin Cernekee1302bac2013-02-13 22:27:08 -0800670}
671
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700672static int alps_decode_dolphin(struct alps_fields *f, unsigned char *p,
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800673 struct psmouse *psmouse)
Dave Turvene75af9e52013-02-21 22:58:28 -0800674{
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800675 u64 palm_data = 0;
676 struct alps_data *priv = psmouse->private;
677
Dave Turvene75af9e52013-02-21 22:58:28 -0800678 f->first_mp = !!(p[0] & 0x02);
679 f->is_mp = !!(p[0] & 0x20);
680
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800681 if (!f->is_mp) {
Hans de Goede02d04252014-07-25 22:43:35 -0700682 f->st.x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
683 f->st.y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
684 f->pressure = (p[0] & 4) ? 0 : p[5] & 0x7f;
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800685 alps_decode_buttons_v3(f, p);
686 } else {
687 f->fingers = ((p[0] & 0x6) >> 1 |
Dave Turvene75af9e52013-02-21 22:58:28 -0800688 (p[0] & 0x10) >> 2);
Dave Turvene75af9e52013-02-21 22:58:28 -0800689
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800690 palm_data = (p[1] & 0x7f) |
691 ((p[2] & 0x7f) << 7) |
692 ((p[4] & 0x7f) << 14) |
693 ((p[5] & 0x7f) << 21) |
694 ((p[3] & 0x07) << 28) |
695 (((u64)p[3] & 0x70) << 27) |
696 (((u64)p[0] & 0x01) << 34);
Dave Turvene75af9e52013-02-21 22:58:28 -0800697
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800698 /* Y-profile is stored in P(0) to p(n-1), n = y_bits; */
699 f->y_map = palm_data & (BIT(priv->y_bits) - 1);
700
701 /* X-profile is stored in p(n) to p(n+m-1), m = x_bits; */
702 f->x_map = (palm_data >> priv->y_bits) &
703 (BIT(priv->x_bits) - 1);
704 }
Hans de Goede38c11eaa2014-07-25 22:48:44 -0700705
706 return 0;
Dave Turvene75af9e52013-02-21 22:58:28 -0800707}
708
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800709static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
Seth Forshee25bded72011-11-07 19:53:36 -0800710{
711 struct alps_data *priv = psmouse->private;
712 unsigned char *packet = psmouse->packet;
Seth Forshee25bded72011-11-07 19:53:36 -0800713 struct input_dev *dev2 = priv->dev2;
Hans de Goede02d04252014-07-25 22:43:35 -0700714 struct alps_fields *f = &priv->f;
715 int fingers = 0;
Kevin Cernekeef85e5002013-02-13 22:26:11 -0800716
Hans de Goede02d04252014-07-25 22:43:35 -0700717 memset(f, 0, sizeof(*f));
718
719 priv->decode_fields(f, packet, psmouse);
Seth Forshee25bded72011-11-07 19:53:36 -0800720
721 /*
Seth Forshee01ce6612011-11-07 19:54:13 -0800722 * There's no single feature of touchpad position and bitmap packets
723 * that can be used to distinguish between them. We rely on the fact
724 * that a bitmap packet should always follow a position packet with
725 * bit 6 of packet[4] set.
Seth Forshee25bded72011-11-07 19:53:36 -0800726 */
727 if (priv->multi_packet) {
Seth Forshee25bded72011-11-07 19:53:36 -0800728 /*
729 * Sometimes a position packet will indicate a multi-packet
730 * sequence, but then what follows is another position
731 * packet. Check for this, and when it happens process the
732 * position packet as usual.
733 */
Hans de Goede02d04252014-07-25 22:43:35 -0700734 if (f->is_mp) {
735 fingers = f->fingers;
Hans de Goede44b77f32015-05-20 14:40:06 -0700736 /*
737 * Bitmap processing uses position packet's coordinate
738 * data, so we need to do decode it first.
739 */
740 priv->decode_fields(f, priv->multi_data, psmouse);
741
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -0800742 if (priv->proto_version == ALPS_PROTO_V3 ||
743 priv->proto_version == ALPS_PROTO_V3_RUSHMORE) {
Hans de Goede02d04252014-07-25 22:43:35 -0700744 if (alps_process_bitmap(priv, f) == 0)
Hans de Goede20bea682014-07-25 22:33:33 -0700745 fingers = 0; /* Use st data */
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800746 } else {
747 /*
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800748 * Since Dolphin's finger number is reliable,
749 * there is no need to compare with bmap_fn.
750 */
Hans de Goede02d04252014-07-25 22:43:35 -0700751 alps_process_bitmap_dolphin(priv, f);
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800752 }
Seth Forshee01ce6612011-11-07 19:54:13 -0800753 } else {
754 priv->multi_packet = 0;
Seth Forshee25bded72011-11-07 19:53:36 -0800755 }
756 }
757
Seth Forshee01ce6612011-11-07 19:54:13 -0800758 /*
759 * Bit 6 of byte 0 is not usually set in position packets. The only
760 * times it seems to be set is in situations where the data is
761 * suspect anyway, e.g. a palm resting flat on the touchpad. Given
762 * this combined with the fact that this bit is useful for filtering
763 * out misidentified bitmap packets, we reject anything with this
764 * bit set.
765 */
Hans de Goede02d04252014-07-25 22:43:35 -0700766 if (f->is_mp)
Seth Forshee01ce6612011-11-07 19:54:13 -0800767 return;
768
Hans de Goede02d04252014-07-25 22:43:35 -0700769 if (!priv->multi_packet && f->first_mp) {
Seth Forshee25bded72011-11-07 19:53:36 -0800770 priv->multi_packet = 1;
Seth Forshee01ce6612011-11-07 19:54:13 -0800771 memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
772 return;
773 }
774
775 priv->multi_packet = 0;
Seth Forshee25bded72011-11-07 19:53:36 -0800776
Seth Forshee25bded72011-11-07 19:53:36 -0800777 /*
778 * Sometimes the hardware sends a single packet with z = 0
779 * in the middle of a stream. Real releases generate packets
780 * with x, y, and z all zero, so these seem to be flukes.
781 * Ignore them.
782 */
Hans de Goede02d04252014-07-25 22:43:35 -0700783 if (f->st.x && f->st.y && !f->pressure)
Seth Forshee25bded72011-11-07 19:53:36 -0800784 return;
785
Hans de Goede68c21872014-07-25 22:47:25 -0700786 alps_report_semi_mt_data(psmouse, fingers);
Seth Forshee25bded72011-11-07 19:53:36 -0800787
Pali Rohár34412ba2015-01-09 12:48:58 -0800788 if ((priv->flags & ALPS_DUALPOINT) &&
789 !(priv->quirks & ALPS_QUIRK_TRACKSTICK_BUTTONS)) {
Hans de Goede02d04252014-07-25 22:43:35 -0700790 input_report_key(dev2, BTN_LEFT, f->ts_left);
791 input_report_key(dev2, BTN_RIGHT, f->ts_right);
792 input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
Seth Forshee25bded72011-11-07 19:53:36 -0800793 input_sync(dev2);
794 }
795}
796
797static void alps_process_packet_v3(struct psmouse *psmouse)
798{
799 unsigned char *packet = psmouse->packet;
800
801 /*
802 * v3 protocol packets come in three types, two representing
803 * touchpad data and one representing trackstick data.
804 * Trackstick packets seem to be distinguished by always
805 * having 0x3f in the last byte. This value has never been
806 * observed in the last byte of either of the other types
807 * of packets.
808 */
809 if (packet[5] == 0x3f) {
810 alps_process_trackstick_packet_v3(psmouse);
811 return;
812 }
813
Yunkang Tangee65d4b2013-12-26 14:54:19 -0800814 alps_process_touchpad_packet_v3_v5(psmouse);
Seth Forshee25bded72011-11-07 19:53:36 -0800815}
816
Yunkang Tang95f75e92013-12-01 22:33:52 -0800817static void alps_process_packet_v6(struct psmouse *psmouse)
818{
819 struct alps_data *priv = psmouse->private;
820 unsigned char *packet = psmouse->packet;
821 struct input_dev *dev = psmouse->dev;
822 struct input_dev *dev2 = priv->dev2;
823 int x, y, z, left, right, middle;
824
825 /*
826 * We can use Byte5 to distinguish if the packet is from Touchpad
827 * or Trackpoint.
828 * Touchpad: 0 - 0x7E
829 * Trackpoint: 0x7F
830 */
831 if (packet[5] == 0x7F) {
832 /* It should be a DualPoint when received Trackpoint packet */
Pali Rohár34412ba2015-01-09 12:48:58 -0800833 if (!(priv->flags & ALPS_DUALPOINT)) {
834 psmouse_warn(psmouse,
835 "Rejected trackstick packet from non DualPoint device");
Yunkang Tang95f75e92013-12-01 22:33:52 -0800836 return;
Pali Rohár34412ba2015-01-09 12:48:58 -0800837 }
Yunkang Tang95f75e92013-12-01 22:33:52 -0800838
839 /* Trackpoint packet */
840 x = packet[1] | ((packet[3] & 0x20) << 2);
841 y = packet[2] | ((packet[3] & 0x40) << 1);
842 z = packet[4];
843 left = packet[3] & 0x01;
844 right = packet[3] & 0x02;
845 middle = packet[3] & 0x04;
846
847 /* To prevent the cursor jump when finger lifted */
848 if (x == 0x7F && y == 0x7F && z == 0x7F)
849 x = y = z = 0;
850
851 /* Divide 4 since trackpoint's speed is too fast */
852 input_report_rel(dev2, REL_X, (char)x / 4);
853 input_report_rel(dev2, REL_Y, -((char)y / 4));
854
855 input_report_key(dev2, BTN_LEFT, left);
856 input_report_key(dev2, BTN_RIGHT, right);
857 input_report_key(dev2, BTN_MIDDLE, middle);
858
859 input_sync(dev2);
860 return;
861 }
862
863 /* Touchpad packet */
864 x = packet[1] | ((packet[3] & 0x78) << 4);
865 y = packet[2] | ((packet[4] & 0x78) << 4);
866 z = packet[5];
867 left = packet[3] & 0x01;
868 right = packet[3] & 0x02;
869
870 if (z > 30)
871 input_report_key(dev, BTN_TOUCH, 1);
872 if (z < 25)
873 input_report_key(dev, BTN_TOUCH, 0);
874
875 if (z > 0) {
876 input_report_abs(dev, ABS_X, x);
877 input_report_abs(dev, ABS_Y, y);
878 }
879
880 input_report_abs(dev, ABS_PRESSURE, z);
881 input_report_key(dev, BTN_TOOL_FINGER, z > 0);
882
883 /* v6 touchpad does not have middle button */
884 input_report_key(dev, BTN_LEFT, left);
885 input_report_key(dev, BTN_RIGHT, right);
886
887 input_sync(dev);
888}
889
Seth Forshee25bded72011-11-07 19:53:36 -0800890static void alps_process_packet_v4(struct psmouse *psmouse)
891{
George Pantalos3b7e09f2012-05-10 22:31:59 -0700892 struct alps_data *priv = psmouse->private;
Seth Forshee25bded72011-11-07 19:53:36 -0800893 unsigned char *packet = psmouse->packet;
Hans de Goede02d04252014-07-25 22:43:35 -0700894 struct alps_fields *f = &priv->f;
Hans de Goede68c21872014-07-25 22:47:25 -0700895 int offset;
George Pantalos3b7e09f2012-05-10 22:31:59 -0700896
897 /*
898 * v4 has a 6-byte encoding for bitmap data, but this data is
899 * broken up between 3 normal packets. Use priv->multi_packet to
900 * track our position in the bitmap packet.
901 */
902 if (packet[6] & 0x40) {
903 /* sync, reset position */
904 priv->multi_packet = 0;
905 }
906
907 if (WARN_ON_ONCE(priv->multi_packet > 2))
908 return;
909
910 offset = 2 * priv->multi_packet;
911 priv->multi_data[offset] = packet[6];
912 priv->multi_data[offset + 1] = packet[7];
913
Hans de Goede44b77f32015-05-20 14:40:06 -0700914 f->left = !!(packet[4] & 0x01);
915 f->right = !!(packet[4] & 0x02);
916
917 f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
918 ((packet[0] & 0x30) >> 4);
919 f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
920 f->pressure = packet[5] & 0x7f;
921
George Pantalos3b7e09f2012-05-10 22:31:59 -0700922 if (++priv->multi_packet > 2) {
923 priv->multi_packet = 0;
924
Hans de Goede02d04252014-07-25 22:43:35 -0700925 f->x_map = ((priv->multi_data[2] & 0x1f) << 10) |
George Pantalos3b7e09f2012-05-10 22:31:59 -0700926 ((priv->multi_data[3] & 0x60) << 3) |
927 ((priv->multi_data[0] & 0x3f) << 2) |
928 ((priv->multi_data[1] & 0x60) >> 5);
Hans de Goede02d04252014-07-25 22:43:35 -0700929 f->y_map = ((priv->multi_data[5] & 0x01) << 10) |
George Pantalos3b7e09f2012-05-10 22:31:59 -0700930 ((priv->multi_data[3] & 0x1f) << 5) |
931 (priv->multi_data[1] & 0x1f);
932
Hans de Goede02d04252014-07-25 22:43:35 -0700933 f->fingers = alps_process_bitmap(priv, f);
George Pantalos3b7e09f2012-05-10 22:31:59 -0700934 }
Seth Forshee25bded72011-11-07 19:53:36 -0800935
Hans de Goede68c21872014-07-25 22:47:25 -0700936 alps_report_semi_mt_data(psmouse, f->fingers);
Seth Forshee25bded72011-11-07 19:53:36 -0800937}
938
Yunkang Tang38088432014-07-26 13:51:41 -0700939static bool alps_is_valid_package_v7(struct psmouse *psmouse)
940{
941 switch (psmouse->pktcnt) {
942 case 3:
943 return (psmouse->packet[2] & 0x40) == 0x40;
944 case 4:
945 return (psmouse->packet[3] & 0x48) == 0x48;
946 case 6:
947 return (psmouse->packet[5] & 0x40) == 0x00;
948 }
949 return true;
950}
951
952static unsigned char alps_get_packet_id_v7(char *byte)
953{
954 unsigned char packet_id;
955
956 if (byte[4] & 0x40)
957 packet_id = V7_PACKET_ID_TWO;
958 else if (byte[4] & 0x01)
959 packet_id = V7_PACKET_ID_MULTI;
960 else if ((byte[0] & 0x10) && !(byte[4] & 0x43))
961 packet_id = V7_PACKET_ID_NEW;
962 else if (byte[1] == 0x00 && byte[4] == 0x00)
963 packet_id = V7_PACKET_ID_IDLE;
964 else
965 packet_id = V7_PACKET_ID_UNKNOWN;
966
967 return packet_id;
968}
969
970static void alps_get_finger_coordinate_v7(struct input_mt_pos *mt,
971 unsigned char *pkt,
972 unsigned char pkt_id)
973{
974 mt[0].x = ((pkt[2] & 0x80) << 4);
975 mt[0].x |= ((pkt[2] & 0x3F) << 5);
976 mt[0].x |= ((pkt[3] & 0x30) >> 1);
977 mt[0].x |= (pkt[3] & 0x07);
978 mt[0].y = (pkt[1] << 3) | (pkt[0] & 0x07);
979
980 mt[1].x = ((pkt[3] & 0x80) << 4);
981 mt[1].x |= ((pkt[4] & 0x80) << 3);
982 mt[1].x |= ((pkt[4] & 0x3F) << 4);
983 mt[1].y = ((pkt[5] & 0x80) << 3);
984 mt[1].y |= ((pkt[5] & 0x3F) << 4);
985
986 switch (pkt_id) {
987 case V7_PACKET_ID_TWO:
988 mt[1].x &= ~0x000F;
989 mt[1].y |= 0x000F;
990 break;
991
992 case V7_PACKET_ID_MULTI:
993 mt[1].x &= ~0x003F;
994 mt[1].y &= ~0x0020;
995 mt[1].y |= ((pkt[4] & 0x02) << 4);
996 mt[1].y |= 0x001F;
997 break;
998
999 case V7_PACKET_ID_NEW:
1000 mt[1].x &= ~0x003F;
1001 mt[1].x |= (pkt[0] & 0x20);
1002 mt[1].y |= 0x000F;
1003 break;
1004 }
1005
1006 mt[0].y = 0x7FF - mt[0].y;
1007 mt[1].y = 0x7FF - mt[1].y;
1008}
1009
1010static int alps_get_mt_count(struct input_mt_pos *mt)
1011{
Hans de Goede7091c442014-12-18 09:53:34 -08001012 int i, fingers = 0;
Yunkang Tang38088432014-07-26 13:51:41 -07001013
Hans de Goede7091c442014-12-18 09:53:34 -08001014 for (i = 0; i < MAX_TOUCHES; i++) {
1015 if (mt[i].x != 0 || mt[i].y != 0)
1016 fingers++;
1017 }
Yunkang Tang38088432014-07-26 13:51:41 -07001018
Hans de Goede7091c442014-12-18 09:53:34 -08001019 return fingers;
Yunkang Tang38088432014-07-26 13:51:41 -07001020}
1021
1022static int alps_decode_packet_v7(struct alps_fields *f,
1023 unsigned char *p,
1024 struct psmouse *psmouse)
1025{
Hans de Goeded27eb792014-12-18 09:55:14 -08001026 struct alps_data *priv = psmouse->private;
Yunkang Tang38088432014-07-26 13:51:41 -07001027 unsigned char pkt_id;
1028
1029 pkt_id = alps_get_packet_id_v7(p);
1030 if (pkt_id == V7_PACKET_ID_IDLE)
1031 return 0;
1032 if (pkt_id == V7_PACKET_ID_UNKNOWN)
1033 return -1;
Hans de Goede8b238112014-12-18 09:52:59 -08001034 /*
1035 * NEW packets are send to indicate a discontinuity in the finger
1036 * coordinate reporting. Specifically a finger may have moved from
1037 * slot 0 to 1 or vice versa. INPUT_MT_TRACK takes care of this for
1038 * us.
1039 *
1040 * NEW packets have 3 problems:
1041 * 1) They do not contain middle / right button info (on non clickpads)
1042 * this can be worked around by preserving the old button state
1043 * 2) They do not contain an accurate fingercount, and they are
1044 * typically send when the number of fingers changes. We cannot use
1045 * the old finger count as that may mismatch with the amount of
1046 * touch coordinates we've available in the NEW packet
1047 * 3) Their x data for the second touch is inaccurate leading to
1048 * a possible jump of the x coordinate by 16 units when the first
1049 * non NEW packet comes in
1050 * Since problems 2 & 3 cannot be worked around, just ignore them.
1051 */
1052 if (pkt_id == V7_PACKET_ID_NEW)
1053 return 1;
Yunkang Tang38088432014-07-26 13:51:41 -07001054
1055 alps_get_finger_coordinate_v7(f->mt, p, pkt_id);
1056
Yunkang Tang38088432014-07-26 13:51:41 -07001057 if (pkt_id == V7_PACKET_ID_TWO)
1058 f->fingers = alps_get_mt_count(f->mt);
Hans de Goede8b238112014-12-18 09:52:59 -08001059 else /* pkt_id == V7_PACKET_ID_MULTI */
Yunkang Tang38088432014-07-26 13:51:41 -07001060 f->fingers = 3 + (p[5] & 0x03);
1061
Hans de Goeded27eb792014-12-18 09:55:14 -08001062 f->left = (p[0] & 0x80) >> 7;
1063 if (priv->flags & ALPS_BUTTONPAD) {
1064 if (p[0] & 0x20)
1065 f->fingers++;
1066 if (p[0] & 0x10)
1067 f->fingers++;
1068 } else {
1069 f->right = (p[0] & 0x20) >> 5;
1070 f->middle = (p[0] & 0x10) >> 4;
1071 }
1072
Hans de Goede7091c442014-12-18 09:53:34 -08001073 /* Sometimes a single touch is reported in mt[1] rather then mt[0] */
1074 if (f->fingers == 1 && f->mt[0].x == 0 && f->mt[0].y == 0) {
1075 f->mt[0].x = f->mt[1].x;
1076 f->mt[0].y = f->mt[1].y;
1077 f->mt[1].x = 0;
1078 f->mt[1].y = 0;
1079 }
1080
Yunkang Tang38088432014-07-26 13:51:41 -07001081 return 0;
1082}
1083
1084static void alps_process_trackstick_packet_v7(struct psmouse *psmouse)
1085{
1086 struct alps_data *priv = psmouse->private;
1087 unsigned char *packet = psmouse->packet;
1088 struct input_dev *dev2 = priv->dev2;
1089 int x, y, z, left, right, middle;
1090
Pali Rohár34412ba2015-01-09 12:48:58 -08001091 /* It should be a DualPoint when received trackstick packet */
1092 if (!(priv->flags & ALPS_DUALPOINT)) {
1093 psmouse_warn(psmouse,
1094 "Rejected trackstick packet from non DualPoint device");
1095 return;
1096 }
1097
Yunkang Tang38088432014-07-26 13:51:41 -07001098 x = ((packet[2] & 0xbf)) | ((packet[3] & 0x10) << 2);
1099 y = (packet[3] & 0x07) | (packet[4] & 0xb8) |
1100 ((packet[3] & 0x20) << 1);
1101 z = (packet[5] & 0x3f) | ((packet[3] & 0x80) >> 1);
1102
1103 left = (packet[1] & 0x01);
1104 right = (packet[1] & 0x02) >> 1;
1105 middle = (packet[1] & 0x04) >> 2;
1106
1107 /* Divide 2 since trackpoint's speed is too fast */
1108 input_report_rel(dev2, REL_X, (char)x / 2);
1109 input_report_rel(dev2, REL_Y, -((char)y / 2));
1110
1111 input_report_key(dev2, BTN_LEFT, left);
1112 input_report_key(dev2, BTN_RIGHT, right);
1113 input_report_key(dev2, BTN_MIDDLE, middle);
1114
1115 input_sync(dev2);
1116}
1117
1118static void alps_process_touchpad_packet_v7(struct psmouse *psmouse)
1119{
1120 struct alps_data *priv = psmouse->private;
1121 struct input_dev *dev = psmouse->dev;
1122 struct alps_fields *f = &priv->f;
1123
1124 memset(f, 0, sizeof(*f));
1125
1126 if (priv->decode_fields(f, psmouse->packet, psmouse))
1127 return;
1128
1129 alps_report_mt_data(psmouse, alps_get_mt_count(f->mt));
1130
1131 input_mt_report_finger_count(dev, f->fingers);
1132
1133 input_report_key(dev, BTN_LEFT, f->left);
1134 input_report_key(dev, BTN_RIGHT, f->right);
1135 input_report_key(dev, BTN_MIDDLE, f->middle);
1136
1137 input_sync(dev);
1138}
1139
1140static void alps_process_packet_v7(struct psmouse *psmouse)
1141{
1142 unsigned char *packet = psmouse->packet;
1143
1144 if (packet[0] == 0x48 && (packet[4] & 0x47) == 0x06)
1145 alps_process_trackstick_packet_v7(psmouse);
1146 else
1147 alps_process_touchpad_packet_v7(psmouse);
1148}
1149
Fengguang Wu07f19e32015-04-10 23:54:31 -07001150static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
Masaki Ota3db5b9f2015-03-27 20:57:52 -07001151{
1152 unsigned char pkt_id = SS4_PACKET_ID_IDLE;
1153
1154 if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 &&
1155 (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) {
1156 pkt_id = SS4_PACKET_ID_IDLE;
1157 } else if (!(byte[3] & 0x10)) {
1158 pkt_id = SS4_PACKET_ID_ONE;
1159 } else if (!(byte[3] & 0x20)) {
1160 pkt_id = SS4_PACKET_ID_TWO;
1161 } else {
1162 pkt_id = SS4_PACKET_ID_MULTI;
1163 }
1164
1165 return pkt_id;
1166}
1167
1168static int alps_decode_ss4_v2(struct alps_fields *f,
1169 unsigned char *p, struct psmouse *psmouse)
1170{
1171 struct alps_data *priv = psmouse->private;
1172 unsigned char pkt_id;
1173 unsigned int no_data_x, no_data_y;
1174
1175 pkt_id = alps_get_pkt_id_ss4_v2(p);
1176
1177 /* Current packet is 1Finger coordinate packet */
1178 switch (pkt_id) {
1179 case SS4_PACKET_ID_ONE:
1180 f->mt[0].x = SS4_1F_X_V2(p);
1181 f->mt[0].y = SS4_1F_Y_V2(p);
1182 f->pressure = ((SS4_1F_Z_V2(p)) * 2) & 0x7f;
1183 f->fingers = 1;
1184 f->first_mp = 0;
1185 f->is_mp = 0;
1186 break;
1187
1188 case SS4_PACKET_ID_TWO:
1189 if (priv->flags & ALPS_BUTTONPAD) {
1190 f->mt[0].x = SS4_BTL_MF_X_V2(p, 0);
1191 f->mt[0].y = SS4_BTL_MF_Y_V2(p, 0);
1192 f->mt[1].x = SS4_BTL_MF_X_V2(p, 1);
1193 f->mt[1].y = SS4_BTL_MF_Y_V2(p, 1);
1194 } else {
1195 f->mt[0].x = SS4_STD_MF_X_V2(p, 0);
1196 f->mt[0].y = SS4_STD_MF_Y_V2(p, 0);
1197 f->mt[1].x = SS4_STD_MF_X_V2(p, 1);
1198 f->mt[1].y = SS4_STD_MF_Y_V2(p, 1);
1199 }
1200 f->pressure = SS4_MF_Z_V2(p, 0) ? 0x30 : 0;
1201
1202 if (SS4_IS_MF_CONTINUE(p)) {
1203 f->first_mp = 1;
1204 } else {
1205 f->fingers = 2;
1206 f->first_mp = 0;
1207 }
1208 f->is_mp = 0;
1209
1210 break;
1211
1212 case SS4_PACKET_ID_MULTI:
1213 if (priv->flags & ALPS_BUTTONPAD) {
1214 f->mt[2].x = SS4_BTL_MF_X_V2(p, 0);
1215 f->mt[2].y = SS4_BTL_MF_Y_V2(p, 0);
1216 f->mt[3].x = SS4_BTL_MF_X_V2(p, 1);
1217 f->mt[3].y = SS4_BTL_MF_Y_V2(p, 1);
1218 no_data_x = SS4_MFPACKET_NO_AX_BL;
1219 no_data_y = SS4_MFPACKET_NO_AY_BL;
1220 } else {
1221 f->mt[2].x = SS4_STD_MF_X_V2(p, 0);
1222 f->mt[2].y = SS4_STD_MF_Y_V2(p, 0);
1223 f->mt[3].x = SS4_STD_MF_X_V2(p, 1);
1224 f->mt[3].y = SS4_STD_MF_Y_V2(p, 1);
1225 no_data_x = SS4_MFPACKET_NO_AX;
1226 no_data_y = SS4_MFPACKET_NO_AY;
1227 }
1228
1229 f->first_mp = 0;
1230 f->is_mp = 1;
1231
1232 if (SS4_IS_5F_DETECTED(p)) {
1233 f->fingers = 5;
1234 } else if (f->mt[3].x == no_data_x &&
1235 f->mt[3].y == no_data_y) {
1236 f->mt[3].x = 0;
1237 f->mt[3].y = 0;
1238 f->fingers = 3;
1239 } else {
1240 f->fingers = 4;
1241 }
1242 break;
1243
1244 case SS4_PACKET_ID_IDLE:
1245 default:
1246 memset(f, 0, sizeof(struct alps_fields));
1247 break;
1248 }
1249
1250 f->left = !!(SS4_BTN_V2(p) & 0x01);
1251 if (!(priv->flags & ALPS_BUTTONPAD)) {
1252 f->right = !!(SS4_BTN_V2(p) & 0x02);
1253 f->middle = !!(SS4_BTN_V2(p) & 0x04);
1254 }
1255
1256 return 0;
1257}
1258
1259static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
1260{
1261 struct alps_data *priv = psmouse->private;
1262 unsigned char *packet = psmouse->packet;
1263 struct input_dev *dev = psmouse->dev;
1264 struct alps_fields *f = &priv->f;
1265
1266 memset(f, 0, sizeof(struct alps_fields));
1267 priv->decode_fields(f, packet, psmouse);
1268 if (priv->multi_packet) {
1269 /*
1270 * Sometimes the first packet will indicate a multi-packet
1271 * sequence, but sometimes the next multi-packet would not
1272 * come. Check for this, and when it happens process the
1273 * position packet as usual.
1274 */
1275 if (f->is_mp) {
1276 /* Now process the 1st packet */
1277 priv->decode_fields(f, priv->multi_data, psmouse);
1278 } else {
1279 priv->multi_packet = 0;
1280 }
1281 }
1282
1283 /*
1284 * "f.is_mp" would always be '0' after merging the 1st and 2nd packet.
1285 * When it is set, it means 2nd packet comes without 1st packet come.
1286 */
1287 if (f->is_mp)
1288 return;
1289
1290 /* Save the first packet */
1291 if (!priv->multi_packet && f->first_mp) {
1292 priv->multi_packet = 1;
1293 memcpy(priv->multi_data, packet, sizeof(priv->multi_data));
1294 return;
1295 }
1296
1297 priv->multi_packet = 0;
1298
1299 alps_report_mt_data(psmouse, (f->fingers <= 4) ? f->fingers : 4);
1300
1301 input_mt_report_finger_count(dev, f->fingers);
1302
1303 input_report_key(dev, BTN_LEFT, f->left);
1304 input_report_key(dev, BTN_RIGHT, f->right);
1305 input_report_key(dev, BTN_MIDDLE, f->middle);
1306
1307 input_report_abs(dev, ABS_PRESSURE, f->pressure);
1308 input_sync(dev);
1309}
1310
1311static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
1312{
1313 if (psmouse->pktcnt == 4 && ((psmouse->packet[3] & 0x08) != 0x08))
1314 return false;
1315 if (psmouse->pktcnt == 6 && ((psmouse->packet[5] & 0x10) != 0x0))
1316 return false;
1317 return true;
1318}
1319
Pali Rohár04aae282015-01-14 13:18:30 -08001320static DEFINE_MUTEX(alps_mutex);
1321
1322static void alps_register_bare_ps2_mouse(struct work_struct *work)
1323{
1324 struct alps_data *priv =
1325 container_of(work, struct alps_data, dev3_register_work.work);
1326 struct psmouse *psmouse = priv->psmouse;
1327 struct input_dev *dev3;
1328 int error = 0;
1329
1330 mutex_lock(&alps_mutex);
1331
1332 if (priv->dev3)
1333 goto out;
1334
1335 dev3 = input_allocate_device();
1336 if (!dev3) {
1337 psmouse_err(psmouse, "failed to allocate secondary device\n");
1338 error = -ENOMEM;
1339 goto out;
1340 }
1341
1342 snprintf(priv->phys3, sizeof(priv->phys3), "%s/%s",
1343 psmouse->ps2dev.serio->phys,
1344 (priv->dev2 ? "input2" : "input1"));
1345 dev3->phys = priv->phys3;
1346
1347 /*
1348 * format of input device name is: "protocol vendor name"
1349 * see function psmouse_switch_protocol() in psmouse-base.c
1350 */
1351 dev3->name = "PS/2 ALPS Mouse";
1352
1353 dev3->id.bustype = BUS_I8042;
1354 dev3->id.vendor = 0x0002;
1355 dev3->id.product = PSMOUSE_PS2;
1356 dev3->id.version = 0x0000;
1357 dev3->dev.parent = &psmouse->ps2dev.serio->dev;
1358
1359 input_set_capability(dev3, EV_REL, REL_X);
1360 input_set_capability(dev3, EV_REL, REL_Y);
1361 input_set_capability(dev3, EV_KEY, BTN_LEFT);
1362 input_set_capability(dev3, EV_KEY, BTN_RIGHT);
1363 input_set_capability(dev3, EV_KEY, BTN_MIDDLE);
1364
1365 __set_bit(INPUT_PROP_POINTER, dev3->propbit);
1366
1367 error = input_register_device(dev3);
1368 if (error) {
1369 psmouse_err(psmouse,
1370 "failed to register secondary device: %d\n",
1371 error);
1372 input_free_device(dev3);
1373 goto out;
1374 }
1375
1376 priv->dev3 = dev3;
1377
1378out:
1379 /*
1380 * Save the error code so that we can detect that we
1381 * already tried to create the device.
1382 */
1383 if (error)
1384 priv->dev3 = ERR_PTR(error);
1385
1386 mutex_unlock(&alps_mutex);
1387}
1388
Hans de Goede59c30af2015-04-03 17:14:40 -07001389static void alps_report_bare_ps2_packet(struct psmouse *psmouse,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001390 unsigned char packet[],
1391 bool report_buttons)
1392{
Hans de Goede59c30af2015-04-03 17:14:40 -07001393 struct alps_data *priv = psmouse->private;
1394 struct input_dev *dev;
1395
Hans de Goedee3a79212015-04-03 17:20:05 -07001396 /* Figure out which device to use to report the bare packet */
1397 if (priv->proto_version == ALPS_PROTO_V2 &&
1398 (priv->flags & ALPS_DUALPOINT)) {
1399 /* On V2 devices the DualPoint Stick reports bare packets */
1400 dev = priv->dev2;
1401 } else if (unlikely(IS_ERR_OR_NULL(priv->dev3))) {
Hans de Goede59c30af2015-04-03 17:14:40 -07001402 /* Register dev3 mouse if we received PS/2 packet first time */
1403 if (!IS_ERR(priv->dev3))
1404 psmouse_queue_work(psmouse, &priv->dev3_register_work,
1405 0);
1406 return;
1407 } else {
1408 dev = priv->dev3;
1409 }
1410
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001411 if (report_buttons)
Pali Rohár04aae282015-01-14 13:18:30 -08001412 alps_report_buttons(dev, NULL,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001413 packet[0] & 1, packet[0] & 2, packet[0] & 4);
1414
Pali Rohár04aae282015-01-14 13:18:30 -08001415 input_report_rel(dev, REL_X,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001416 packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
Pali Rohár04aae282015-01-14 13:18:30 -08001417 input_report_rel(dev, REL_Y,
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001418 packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
1419
Pali Rohár04aae282015-01-14 13:18:30 -08001420 input_sync(dev);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001421}
1422
1423static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424{
1425 struct alps_data *priv = psmouse->private;
1426
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001427 if (psmouse->pktcnt < 6)
1428 return PSMOUSE_GOOD_DATA;
1429
1430 if (psmouse->pktcnt == 6) {
1431 /*
1432 * Start a timer to flush the packet if it ends up last
1433 * 6-byte packet in the stream. Timer needs to fire
1434 * psmouse core times out itself. 20 ms should be enough
1435 * to decide if we are getting more data or not.
1436 */
1437 mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20));
1438 return PSMOUSE_GOOD_DATA;
1439 }
1440
1441 del_timer(&priv->timer);
1442
1443 if (psmouse->packet[6] & 0x80) {
1444
1445 /*
1446 * Highest bit is set - that means we either had
1447 * complete ALPS packet and this is start of the
1448 * next packet or we got garbage.
1449 */
1450
1451 if (((psmouse->packet[3] |
1452 psmouse->packet[4] |
1453 psmouse->packet[5]) & 0x80) ||
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001454 (!alps_is_valid_first_byte(priv, psmouse->packet[6]))) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001455 psmouse_dbg(psmouse,
Andy Shevchenko3b112922012-10-30 00:24:41 -07001456 "refusing packet %4ph (suspected interleaved ps/2)\n",
1457 psmouse->packet + 3);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001458 return PSMOUSE_BAD_DATA;
1459 }
1460
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08001461 priv->process_packet(psmouse);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001462
1463 /* Continue with the next packet */
1464 psmouse->packet[0] = psmouse->packet[6];
1465 psmouse->pktcnt = 1;
1466
1467 } else {
1468
1469 /*
1470 * High bit is 0 - that means that we indeed got a PS/2
1471 * packet in the middle of ALPS packet.
1472 *
1473 * There is also possibility that we got 6-byte ALPS
1474 * packet followed by 3-byte packet from trackpoint. We
1475 * can not distinguish between these 2 scenarios but
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001476 * because the latter is unlikely to happen in course of
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001477 * normal operation (user would need to press all
1478 * buttons on the pad and start moving trackpoint
1479 * without touching the pad surface) we assume former.
1480 * Even if we are wrong the wost thing that would happen
1481 * the cursor would jump but we should not get protocol
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001482 * de-synchronization.
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001483 */
1484
Hans de Goede59c30af2015-04-03 17:14:40 -07001485 alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3],
1486 false);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001487
1488 /*
1489 * Continue with the standard ALPS protocol handling,
1490 * but make sure we won't process it as an interleaved
1491 * packet again, which may happen if all buttons are
1492 * pressed. To avoid this let's reset the 4th bit which
1493 * is normally 1.
1494 */
1495 psmouse->packet[3] = psmouse->packet[6] & 0xf7;
1496 psmouse->pktcnt = 4;
1497 }
1498
1499 return PSMOUSE_GOOD_DATA;
1500}
1501
1502static void alps_flush_packet(unsigned long data)
1503{
1504 struct psmouse *psmouse = (struct psmouse *)data;
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08001505 struct alps_data *priv = psmouse->private;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001506
1507 serio_pause_rx(psmouse->ps2dev.serio);
1508
Seth Forsheeb46615f2011-11-07 19:53:30 -08001509 if (psmouse->pktcnt == psmouse->pktsize) {
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001510
1511 /*
1512 * We did not any more data in reasonable amount of time.
1513 * Validate the last 3 bytes and process as a standard
1514 * ALPS packet.
1515 */
1516 if ((psmouse->packet[3] |
1517 psmouse->packet[4] |
1518 psmouse->packet[5]) & 0x80) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001519 psmouse_dbg(psmouse,
Andy Shevchenko3b112922012-10-30 00:24:41 -07001520 "refusing packet %3ph (suspected interleaved ps/2)\n",
1521 psmouse->packet + 3);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001522 } else {
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08001523 priv->process_packet(psmouse);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001524 }
1525 psmouse->pktcnt = 0;
1526 }
1527
1528 serio_continue_rx(psmouse->ps2dev.serio);
1529}
1530
1531static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
1532{
1533 struct alps_data *priv = psmouse->private;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001534
Pali Rohár4ab8f7f2014-11-08 12:45:23 -08001535 /*
1536 * Check if we are dealing with a bare PS/2 packet, presumably from
1537 * a device connected to the external PS/2 port. Because bare PS/2
1538 * protocol does not have enough constant bits to self-synchronize
1539 * properly we only do this if the device is fully synchronized.
Masaki Ota3db5b9f2015-03-27 20:57:52 -07001540 * Can not distinguish V8's first byte from PS/2 packet's
Pali Rohár4ab8f7f2014-11-08 12:45:23 -08001541 */
Masaki Ota3db5b9f2015-03-27 20:57:52 -07001542 if (priv->proto_version != ALPS_PROTO_V8 &&
1543 !psmouse->out_of_sync_cnt &&
1544 (psmouse->packet[0] & 0xc8) == 0x08) {
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 if (psmouse->pktcnt == 3) {
Hans de Goede59c30af2015-04-03 17:14:40 -07001547 alps_report_bare_ps2_packet(psmouse, psmouse->packet,
1548 true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 return PSMOUSE_FULL_PACKET;
1550 }
1551 return PSMOUSE_GOOD_DATA;
1552 }
1553
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001554 /* Check for PS/2 packet stuffed in the middle of ALPS packet. */
1555
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001556 if ((priv->flags & ALPS_PS2_INTERLEAVED) &&
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001557 psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) {
1558 return alps_handle_interleaved_ps2(psmouse);
1559 }
1560
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001561 if (!alps_is_valid_first_byte(priv, psmouse->packet[0])) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001562 psmouse_dbg(psmouse,
1563 "refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n",
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001564 psmouse->packet[0], priv->mask0, priv->byte0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 return PSMOUSE_BAD_DATA;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Seth Forsheeb46615f2011-11-07 19:53:30 -08001568 /* Bytes 2 - pktsize should have 0 in the highest bit */
Pali Rohára7ef82a2014-11-08 23:36:09 -08001569 if (priv->proto_version < ALPS_PROTO_V5 &&
Dave Turvene75af9e52013-02-21 22:58:28 -08001570 psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001571 (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001572 psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
1573 psmouse->pktcnt - 1,
1574 psmouse->packet[psmouse->pktcnt - 1]);
Pali Rohára7ef82a2014-11-08 23:36:09 -08001575
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -08001576 if (priv->proto_version == ALPS_PROTO_V3_RUSHMORE &&
Pali Rohára7ef82a2014-11-08 23:36:09 -08001577 psmouse->pktcnt == psmouse->pktsize) {
1578 /*
1579 * Some Dell boxes, such as Latitude E6440 or E7440
1580 * with closed lid, quite often smash last byte of
1581 * otherwise valid packet with 0xff. Given that the
1582 * next packet is very likely to be valid let's
1583 * report PSMOUSE_FULL_PACKET but not process data,
1584 * rather than reporting PSMOUSE_BAD_DATA and
1585 * filling the logs.
1586 */
1587 return PSMOUSE_FULL_PACKET;
1588 }
1589
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 return PSMOUSE_BAD_DATA;
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08001591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
Masaki Ota3db5b9f2015-03-27 20:57:52 -07001593 if ((priv->proto_version == ALPS_PROTO_V7 &&
1594 !alps_is_valid_package_v7(psmouse)) ||
1595 (priv->proto_version == ALPS_PROTO_V8 &&
1596 !alps_is_valid_package_ss4_v2(psmouse))) {
Yunkang Tang38088432014-07-26 13:51:41 -07001597 psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
1598 psmouse->pktcnt - 1,
1599 psmouse->packet[psmouse->pktcnt - 1]);
1600 return PSMOUSE_BAD_DATA;
1601 }
1602
Seth Forsheeb46615f2011-11-07 19:53:30 -08001603 if (psmouse->pktcnt == psmouse->pktsize) {
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08001604 priv->process_packet(psmouse);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 return PSMOUSE_FULL_PACKET;
1606 }
1607
1608 return PSMOUSE_GOOD_DATA;
1609}
1610
Seth Forshee25bded72011-11-07 19:53:36 -08001611static int alps_command_mode_send_nibble(struct psmouse *psmouse, int nibble)
1612{
1613 struct ps2dev *ps2dev = &psmouse->ps2dev;
1614 struct alps_data *priv = psmouse->private;
1615 int command;
1616 unsigned char *param;
1617 unsigned char dummy[4];
1618
1619 BUG_ON(nibble > 0xf);
1620
1621 command = priv->nibble_commands[nibble].command;
1622 param = (command & 0x0f00) ?
1623 dummy : (unsigned char *)&priv->nibble_commands[nibble].data;
1624
1625 if (ps2_command(ps2dev, param, command))
1626 return -1;
1627
1628 return 0;
1629}
1630
1631static int alps_command_mode_set_addr(struct psmouse *psmouse, int addr)
1632{
1633 struct ps2dev *ps2dev = &psmouse->ps2dev;
1634 struct alps_data *priv = psmouse->private;
1635 int i, nibble;
1636
1637 if (ps2_command(ps2dev, NULL, priv->addr_command))
1638 return -1;
1639
1640 for (i = 12; i >= 0; i -= 4) {
1641 nibble = (addr >> i) & 0xf;
1642 if (alps_command_mode_send_nibble(psmouse, nibble))
1643 return -1;
1644 }
1645
1646 return 0;
1647}
1648
1649static int __alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
1650{
1651 struct ps2dev *ps2dev = &psmouse->ps2dev;
1652 unsigned char param[4];
1653
1654 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
1655 return -1;
1656
1657 /*
1658 * The address being read is returned in the first two bytes
1659 * of the result. Check that this address matches the expected
1660 * address.
1661 */
1662 if (addr != ((param[0] << 8) | param[1]))
1663 return -1;
1664
1665 return param[2];
1666}
1667
1668static int alps_command_mode_read_reg(struct psmouse *psmouse, int addr)
1669{
1670 if (alps_command_mode_set_addr(psmouse, addr))
1671 return -1;
1672 return __alps_command_mode_read_reg(psmouse, addr);
1673}
1674
1675static int __alps_command_mode_write_reg(struct psmouse *psmouse, u8 value)
1676{
1677 if (alps_command_mode_send_nibble(psmouse, (value >> 4) & 0xf))
1678 return -1;
1679 if (alps_command_mode_send_nibble(psmouse, value & 0xf))
1680 return -1;
1681 return 0;
1682}
1683
1684static int alps_command_mode_write_reg(struct psmouse *psmouse, int addr,
1685 u8 value)
1686{
1687 if (alps_command_mode_set_addr(psmouse, addr))
1688 return -1;
1689 return __alps_command_mode_write_reg(psmouse, value);
1690}
1691
Kevin Cernekee24ba9702013-02-13 22:19:01 -08001692static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
1693 int repeated_command, unsigned char *param)
1694{
1695 struct ps2dev *ps2dev = &psmouse->ps2dev;
1696
1697 param[0] = 0;
1698 if (init_command && ps2_command(ps2dev, param, init_command))
1699 return -EIO;
1700
1701 if (ps2_command(ps2dev, NULL, repeated_command) ||
1702 ps2_command(ps2dev, NULL, repeated_command) ||
1703 ps2_command(ps2dev, NULL, repeated_command))
1704 return -EIO;
1705
1706 param[0] = param[1] = param[2] = 0xff;
1707 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
1708 return -EIO;
1709
Dmitry Torokhov39fbe582013-02-14 09:04:24 -08001710 psmouse_dbg(psmouse, "%2.2X report: %3ph\n",
1711 repeated_command, param);
Kevin Cernekee24ba9702013-02-13 22:19:01 -08001712 return 0;
1713}
1714
Yunkang Tang38088432014-07-26 13:51:41 -07001715static bool alps_check_valid_firmware_id(unsigned char id[])
1716{
1717 if (id[0] == 0x73)
1718 return true;
1719
1720 if (id[0] == 0x88 &&
1721 (id[1] == 0x07 ||
1722 id[1] == 0x08 ||
1723 (id[1] & 0xf0) == 0xb0 ||
1724 (id[1] & 0xf0) == 0xc0)) {
1725 return true;
1726 }
1727
1728 return false;
1729}
1730
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08001731static int alps_enter_command_mode(struct psmouse *psmouse)
Seth Forshee25bded72011-11-07 19:53:36 -08001732{
1733 unsigned char param[4];
Seth Forshee25bded72011-11-07 19:53:36 -08001734
Kevin Cernekee24ba9702013-02-13 22:19:01 -08001735 if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_RESET_WRAP, param)) {
Seth Forshee25bded72011-11-07 19:53:36 -08001736 psmouse_err(psmouse, "failed to enter command mode\n");
1737 return -1;
1738 }
1739
Yunkang Tang38088432014-07-26 13:51:41 -07001740 if (!alps_check_valid_firmware_id(param)) {
Seth Forshee25bded72011-11-07 19:53:36 -08001741 psmouse_dbg(psmouse,
Kevin Cernekee24ba9702013-02-13 22:19:01 -08001742 "unknown response while entering command mode\n");
Seth Forshee25bded72011-11-07 19:53:36 -08001743 return -1;
1744 }
Seth Forshee25bded72011-11-07 19:53:36 -08001745 return 0;
1746}
1747
1748static inline int alps_exit_command_mode(struct psmouse *psmouse)
1749{
1750 struct ps2dev *ps2dev = &psmouse->ps2dev;
1751 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM))
1752 return -1;
1753 return 0;
1754}
1755
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756/*
1757 * For DualPoint devices select the device that should respond to
1758 * subsequent commands. It looks like glidepad is behind stickpointer,
1759 * I'd thought it would be other way around...
1760 */
Seth Forshee25bded72011-11-07 19:53:36 -08001761static int alps_passthrough_mode_v2(struct psmouse *psmouse, bool enable)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762{
1763 struct ps2dev *ps2dev = &psmouse->ps2dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11;
1765
1766 if (ps2_command(ps2dev, NULL, cmd) ||
1767 ps2_command(ps2dev, NULL, cmd) ||
1768 ps2_command(ps2dev, NULL, cmd) ||
1769 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
1770 return -1;
1771
1772 /* we may get 3 more bytes, just ignore them */
Dmitry Torokhovc6117632005-06-01 02:39:51 -05001773 ps2_drain(ps2dev, 3, 100);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774
1775 return 0;
1776}
1777
Seth Forshee25bded72011-11-07 19:53:36 -08001778static int alps_absolute_mode_v1_v2(struct psmouse *psmouse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779{
1780 struct ps2dev *ps2dev = &psmouse->ps2dev;
1781
1782 /* Try ALPS magic knock - 4 disable before enable */
1783 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1784 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1785 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1786 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1787 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE))
1788 return -1;
1789
1790 /*
1791 * Switch mouse to poll (remote) mode so motion data will not
1792 * get in our way
1793 */
1794 return ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETPOLL);
1795}
1796
Yunkang Tang95f75e92013-12-01 22:33:52 -08001797static int alps_monitor_mode_send_word(struct psmouse *psmouse, u16 word)
1798{
1799 int i, nibble;
1800
1801 /*
1802 * b0-b11 are valid bits, send sequence is inverse.
1803 * e.g. when word = 0x0123, nibble send sequence is 3, 2, 1
1804 */
1805 for (i = 0; i <= 8; i += 4) {
1806 nibble = (word >> i) & 0xf;
1807 if (alps_command_mode_send_nibble(psmouse, nibble))
1808 return -1;
1809 }
1810
1811 return 0;
1812}
1813
1814static int alps_monitor_mode_write_reg(struct psmouse *psmouse,
1815 u16 addr, u16 value)
1816{
1817 struct ps2dev *ps2dev = &psmouse->ps2dev;
1818
1819 /* 0x0A0 is the command to write the word */
1820 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE) ||
1821 alps_monitor_mode_send_word(psmouse, 0x0A0) ||
1822 alps_monitor_mode_send_word(psmouse, addr) ||
1823 alps_monitor_mode_send_word(psmouse, value) ||
1824 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE))
1825 return -1;
1826
1827 return 0;
1828}
1829
1830static int alps_monitor_mode(struct psmouse *psmouse, bool enable)
1831{
1832 struct ps2dev *ps2dev = &psmouse->ps2dev;
1833
1834 if (enable) {
1835 /* EC E9 F5 F5 E7 E6 E7 E9 to enter monitor mode */
1836 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
1837 ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO) ||
1838 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1839 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1840 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1841 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1842 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE21) ||
1843 ps2_command(ps2dev, NULL, PSMOUSE_CMD_GETINFO))
1844 return -1;
1845 } else {
1846 /* EC to exit monitor mode */
1847 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP))
1848 return -1;
1849 }
1850
1851 return 0;
1852}
1853
1854static int alps_absolute_mode_v6(struct psmouse *psmouse)
1855{
1856 u16 reg_val = 0x181;
1857 int ret = -1;
1858
1859 /* enter monitor mode, to write the register */
1860 if (alps_monitor_mode(psmouse, true))
1861 return -1;
1862
1863 ret = alps_monitor_mode_write_reg(psmouse, 0x000, reg_val);
1864
1865 if (alps_monitor_mode(psmouse, false))
1866 ret = -1;
1867
1868 return ret;
1869}
1870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871static int alps_get_status(struct psmouse *psmouse, char *param)
1872{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 /* Get status: 0xF5 0xF5 0xF5 0xE9 */
Kevin Cernekee24ba9702013-02-13 22:19:01 -08001874 if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_DISABLE, param))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 return -1;
1876
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 return 0;
1878}
1879
1880/*
1881 * Turn touchpad tapping on or off. The sequences are:
1882 * 0xE9 0xF5 0xF5 0xF3 0x0A to enable,
1883 * 0xE9 0xF5 0xF5 0xE8 0x00 to disable.
1884 * My guess that 0xE9 (GetInfo) is here as a sync point.
1885 * For models that also have stickpointer (DualPoints) its tapping
1886 * is controlled separately (0xE6 0xE6 0xE6 0xF3 0x14|0x0A) but
1887 * we don't fiddle with it.
1888 */
1889static int alps_tap_mode(struct psmouse *psmouse, int enable)
1890{
1891 struct ps2dev *ps2dev = &psmouse->ps2dev;
1892 int cmd = enable ? PSMOUSE_CMD_SETRATE : PSMOUSE_CMD_SETRES;
1893 unsigned char tap_arg = enable ? 0x0A : 0x00;
1894 unsigned char param[4];
1895
1896 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO) ||
1897 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1898 ps2_command(ps2dev, NULL, PSMOUSE_CMD_DISABLE) ||
1899 ps2_command(ps2dev, &tap_arg, cmd))
1900 return -1;
1901
1902 if (alps_get_status(psmouse, param))
1903 return -1;
1904
1905 return 0;
1906}
1907
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05001908/*
1909 * alps_poll() - poll the touchpad for current motion packet.
1910 * Used in resync.
1911 */
1912static int alps_poll(struct psmouse *psmouse)
1913{
1914 struct alps_data *priv = psmouse->private;
Seth Forsheeb46615f2011-11-07 19:53:30 -08001915 unsigned char buf[sizeof(psmouse->packet)];
Dmitry Torokhovb7802c52009-09-09 19:13:20 -07001916 bool poll_failed;
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05001917
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001918 if (priv->flags & ALPS_PASS)
Seth Forshee25bded72011-11-07 19:53:36 -08001919 alps_passthrough_mode_v2(psmouse, true);
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05001920
1921 poll_failed = ps2_command(&psmouse->ps2dev, buf,
1922 PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0;
1923
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001924 if (priv->flags & ALPS_PASS)
Seth Forshee25bded72011-11-07 19:53:36 -08001925 alps_passthrough_mode_v2(psmouse, false);
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05001926
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001927 if (poll_failed || (buf[0] & priv->mask0) != priv->byte0)
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05001928 return -1;
1929
1930 if ((psmouse->badbyte & 0xc8) == 0x08) {
1931/*
1932 * Poll the track stick ...
1933 */
1934 if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8)))
1935 return -1;
1936 }
1937
1938 memcpy(psmouse->packet, buf, sizeof(buf));
1939 return 0;
1940}
1941
Seth Forshee25bded72011-11-07 19:53:36 -08001942static int alps_hw_init_v1_v2(struct psmouse *psmouse)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943{
1944 struct alps_data *priv = psmouse->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001946 if ((priv->flags & ALPS_PASS) &&
Seth Forshee25bded72011-11-07 19:53:36 -08001947 alps_passthrough_mode_v2(psmouse, true)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 return -1;
Dmitry Torokhovb7802c52009-09-09 19:13:20 -07001949 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950
Dmitry Torokhovb7802c52009-09-09 19:13:20 -07001951 if (alps_tap_mode(psmouse, true)) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001952 psmouse_warn(psmouse, "Failed to enable hardware tapping\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001953 return -1;
Peter Osterlund963f6262005-07-11 01:08:04 -05001954 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955
Seth Forshee25bded72011-11-07 19:53:36 -08001956 if (alps_absolute_mode_v1_v2(psmouse)) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001957 psmouse_err(psmouse, "Failed to enable absolute mode\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 return -1;
1959 }
1960
Kevin Cernekee99df65e2013-02-13 20:56:33 -08001961 if ((priv->flags & ALPS_PASS) &&
Seth Forshee25bded72011-11-07 19:53:36 -08001962 alps_passthrough_mode_v2(psmouse, false)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 return -1;
Dmitry Torokhovb7802c52009-09-09 19:13:20 -07001964 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001965
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04001966 /* ALPS needs stream mode, otherwise it won't report any data */
1967 if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSTREAM)) {
Dmitry Torokhovb5d21702011-10-10 18:27:03 -07001968 psmouse_err(psmouse, "Failed to enable stream mode\n");
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04001969 return -1;
1970 }
1971
1972 return 0;
1973}
1974
Yunkang Tang95f75e92013-12-01 22:33:52 -08001975static int alps_hw_init_v6(struct psmouse *psmouse)
1976{
1977 unsigned char param[2] = {0xC8, 0x14};
1978
1979 /* Enter passthrough mode to let trackpoint enter 6byte raw mode */
1980 if (alps_passthrough_mode_v2(psmouse, true))
1981 return -1;
1982
1983 if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1984 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1985 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
1986 ps2_command(&psmouse->ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
1987 ps2_command(&psmouse->ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
1988 return -1;
1989
1990 if (alps_passthrough_mode_v2(psmouse, false))
1991 return -1;
1992
1993 if (alps_absolute_mode_v6(psmouse)) {
1994 psmouse_err(psmouse, "Failed to enable absolute mode\n");
1995 return -1;
1996 }
1997
1998 return 0;
1999}
2000
Seth Forshee25bded72011-11-07 19:53:36 -08002001/*
Kevin Cernekeecd401202013-02-13 22:28:07 -08002002 * Enable or disable passthrough mode to the trackstick.
Seth Forshee25bded72011-11-07 19:53:36 -08002003 */
Kevin Cernekeecd401202013-02-13 22:28:07 -08002004static int alps_passthrough_mode_v3(struct psmouse *psmouse,
2005 int reg_base, bool enable)
Seth Forshee25bded72011-11-07 19:53:36 -08002006{
Kevin Cernekeecd401202013-02-13 22:28:07 -08002007 int reg_val, ret = -1;
Seth Forshee25bded72011-11-07 19:53:36 -08002008
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002009 if (alps_enter_command_mode(psmouse))
Seth Forshee25bded72011-11-07 19:53:36 -08002010 return -1;
2011
Kevin Cernekeecd401202013-02-13 22:28:07 -08002012 reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
2013 if (reg_val == -1)
2014 goto error;
2015
Seth Forshee25bded72011-11-07 19:53:36 -08002016 if (enable)
2017 reg_val |= 0x01;
2018 else
2019 reg_val &= ~0x01;
2020
Kevin Cernekeecd401202013-02-13 22:28:07 -08002021 ret = __alps_command_mode_write_reg(psmouse, reg_val);
Seth Forshee25bded72011-11-07 19:53:36 -08002022
Kevin Cernekeecd401202013-02-13 22:28:07 -08002023error:
2024 if (alps_exit_command_mode(psmouse))
2025 ret = -1;
2026 return ret;
Seth Forshee25bded72011-11-07 19:53:36 -08002027}
2028
2029/* Must be in command mode when calling this function */
2030static int alps_absolute_mode_v3(struct psmouse *psmouse)
2031{
2032 int reg_val;
2033
2034 reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
2035 if (reg_val == -1)
2036 return -1;
2037
2038 reg_val |= 0x06;
2039 if (__alps_command_mode_write_reg(psmouse, reg_val))
2040 return -1;
2041
2042 return 0;
2043}
2044
Kevin Cernekeecd401202013-02-13 22:28:07 -08002045static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
2046{
2047 int ret = -EIO, reg_val;
2048
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002049 if (alps_enter_command_mode(psmouse))
Kevin Cernekeecd401202013-02-13 22:28:07 -08002050 goto error;
2051
2052 reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
2053 if (reg_val == -1)
2054 goto error;
2055
2056 /* bit 7: trackstick is present */
2057 ret = reg_val & 0x80 ? 0 : -ENODEV;
2058
2059error:
2060 alps_exit_command_mode(psmouse);
2061 return ret;
2062}
2063
2064static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
2065{
2066 struct ps2dev *ps2dev = &psmouse->ps2dev;
2067 int ret = 0;
2068 unsigned char param[4];
2069
2070 if (alps_passthrough_mode_v3(psmouse, reg_base, true))
2071 return -EIO;
2072
2073 /*
2074 * E7 report for the trackstick
2075 *
2076 * There have been reports of failures to seem to trace back
2077 * to the above trackstick check failing. When these occur
2078 * this E7 report fails, so when that happens we continue
2079 * with the assumption that there isn't a trackstick after
2080 * all.
2081 */
2082 if (alps_rpt_cmd(psmouse, 0, PSMOUSE_CMD_SETSCALE21, param)) {
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002083 psmouse_warn(psmouse, "Failed to initialize trackstick (E7 report failed)\n");
Kevin Cernekeecd401202013-02-13 22:28:07 -08002084 ret = -ENODEV;
2085 } else {
Dmitry Torokhov39fbe582013-02-14 09:04:24 -08002086 psmouse_dbg(psmouse, "trackstick E7 report: %3ph\n", param);
Kevin Cernekeecd401202013-02-13 22:28:07 -08002087
2088 /*
2089 * Not sure what this does, but it is absolutely
2090 * essential. Without it, the touchpad does not
2091 * work at all and the trackstick just emits normal
2092 * PS/2 packets.
2093 */
2094 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
2095 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
2096 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSCALE11) ||
2097 alps_command_mode_send_nibble(psmouse, 0x9) ||
2098 alps_command_mode_send_nibble(psmouse, 0x4)) {
2099 psmouse_err(psmouse,
2100 "Error sending magic E6 sequence\n");
2101 ret = -EIO;
2102 goto error;
2103 }
2104
2105 /*
2106 * This ensures the trackstick packets are in the format
2107 * supported by this driver. If bit 1 isn't set the packet
2108 * format is different.
2109 */
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002110 if (alps_enter_command_mode(psmouse) ||
Kevin Cernekeecd401202013-02-13 22:28:07 -08002111 alps_command_mode_write_reg(psmouse,
2112 reg_base + 0x08, 0x82) ||
2113 alps_exit_command_mode(psmouse))
2114 ret = -EIO;
2115 }
2116
2117error:
2118 if (alps_passthrough_mode_v3(psmouse, reg_base, false))
2119 ret = -EIO;
2120
2121 return ret;
2122}
2123
Seth Forshee25bded72011-11-07 19:53:36 -08002124static int alps_hw_init_v3(struct psmouse *psmouse)
2125{
Seth Forshee25bded72011-11-07 19:53:36 -08002126 struct ps2dev *ps2dev = &psmouse->ps2dev;
2127 int reg_val;
2128 unsigned char param[4];
2129
Kevin Cernekeecd401202013-02-13 22:28:07 -08002130 reg_val = alps_probe_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE);
2131 if (reg_val == -EIO)
2132 goto error;
Dmitry Torokhov39fbe582013-02-14 09:04:24 -08002133
Kevin Cernekeecd401202013-02-13 22:28:07 -08002134 if (reg_val == 0 &&
2135 alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
Seth Forshee25bded72011-11-07 19:53:36 -08002136 goto error;
2137
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002138 if (alps_enter_command_mode(psmouse) ||
Kevin Cernekeecd401202013-02-13 22:28:07 -08002139 alps_absolute_mode_v3(psmouse)) {
Seth Forshee25bded72011-11-07 19:53:36 -08002140 psmouse_err(psmouse, "Failed to enter absolute mode\n");
2141 goto error;
2142 }
2143
2144 reg_val = alps_command_mode_read_reg(psmouse, 0x0006);
2145 if (reg_val == -1)
2146 goto error;
2147 if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
2148 goto error;
2149
2150 reg_val = alps_command_mode_read_reg(psmouse, 0x0007);
2151 if (reg_val == -1)
2152 goto error;
2153 if (__alps_command_mode_write_reg(psmouse, reg_val | 0x01))
2154 goto error;
2155
2156 if (alps_command_mode_read_reg(psmouse, 0x0144) == -1)
2157 goto error;
2158 if (__alps_command_mode_write_reg(psmouse, 0x04))
2159 goto error;
2160
2161 if (alps_command_mode_read_reg(psmouse, 0x0159) == -1)
2162 goto error;
2163 if (__alps_command_mode_write_reg(psmouse, 0x03))
2164 goto error;
2165
2166 if (alps_command_mode_read_reg(psmouse, 0x0163) == -1)
2167 goto error;
2168 if (alps_command_mode_write_reg(psmouse, 0x0163, 0x03))
2169 goto error;
2170
2171 if (alps_command_mode_read_reg(psmouse, 0x0162) == -1)
2172 goto error;
2173 if (alps_command_mode_write_reg(psmouse, 0x0162, 0x04))
2174 goto error;
2175
Seth Forshee25bded72011-11-07 19:53:36 -08002176 alps_exit_command_mode(psmouse);
2177
2178 /* Set rate and enable data reporting */
2179 param[0] = 0x64;
2180 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
2181 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
2182 psmouse_err(psmouse, "Failed to enable data reporting\n");
2183 return -1;
2184 }
2185
2186 return 0;
2187
Seth Forshee25bded72011-11-07 19:53:36 -08002188error:
2189 /*
2190 * Leaving the touchpad in command mode will essentially render
2191 * it unusable until the machine reboots, so exit it here just
2192 * to be safe
2193 */
2194 alps_exit_command_mode(psmouse);
2195 return -1;
2196}
2197
Hans de Goedef3f33c62014-07-29 11:22:07 -07002198static int alps_get_v3_v7_resolution(struct psmouse *psmouse, int reg_pitch)
2199{
2200 int reg, x_pitch, y_pitch, x_electrode, y_electrode, x_phys, y_phys;
2201 struct alps_data *priv = psmouse->private;
2202
2203 reg = alps_command_mode_read_reg(psmouse, reg_pitch);
2204 if (reg < 0)
2205 return reg;
2206
2207 x_pitch = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
2208 x_pitch = 50 + 2 * x_pitch; /* In 0.1 mm units */
2209
2210 y_pitch = (char)reg >> 4; /* sign extend upper 4 bits */
2211 y_pitch = 36 + 2 * y_pitch; /* In 0.1 mm units */
2212
2213 reg = alps_command_mode_read_reg(psmouse, reg_pitch + 1);
2214 if (reg < 0)
2215 return reg;
2216
2217 x_electrode = (char)(reg << 4) >> 4; /* sign extend lower 4 bits */
2218 x_electrode = 17 + x_electrode;
2219
2220 y_electrode = (char)reg >> 4; /* sign extend upper 4 bits */
2221 y_electrode = 13 + y_electrode;
2222
2223 x_phys = x_pitch * (x_electrode - 1); /* In 0.1 mm units */
2224 y_phys = y_pitch * (y_electrode - 1); /* In 0.1 mm units */
2225
2226 priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
2227 priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
2228
2229 psmouse_dbg(psmouse,
2230 "pitch %dx%d num-electrodes %dx%d physical size %dx%d mm res %dx%d\n",
2231 x_pitch, y_pitch, x_electrode, y_electrode,
2232 x_phys / 10, y_phys / 10, priv->x_res, priv->y_res);
2233
2234 return 0;
2235}
2236
Kevin Cernekee1302bac2013-02-13 22:27:08 -08002237static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
2238{
Kevin Cernekeecd401202013-02-13 22:28:07 -08002239 struct alps_data *priv = psmouse->private;
Kevin Cernekee1302bac2013-02-13 22:27:08 -08002240 struct ps2dev *ps2dev = &psmouse->ps2dev;
2241 int reg_val, ret = -1;
2242
Kevin Cernekeecd401202013-02-13 22:28:07 -08002243 if (priv->flags & ALPS_DUALPOINT) {
2244 reg_val = alps_setup_trackstick_v3(psmouse,
2245 ALPS_REG_BASE_RUSHMORE);
2246 if (reg_val == -EIO)
2247 goto error;
Kevin Cernekeecd401202013-02-13 22:28:07 -08002248 }
2249
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002250 if (alps_enter_command_mode(psmouse) ||
Kevin Cernekee1302bac2013-02-13 22:27:08 -08002251 alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
2252 alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
2253 goto error;
2254
Hans de Goedef3f33c62014-07-29 11:22:07 -07002255 if (alps_get_v3_v7_resolution(psmouse, 0xc2da))
2256 goto error;
2257
Kevin Cernekee1302bac2013-02-13 22:27:08 -08002258 reg_val = alps_command_mode_read_reg(psmouse, 0xc2c6);
2259 if (reg_val == -1)
2260 goto error;
2261 if (__alps_command_mode_write_reg(psmouse, reg_val & 0xfd))
2262 goto error;
2263
2264 if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
2265 goto error;
2266
2267 /* enter absolute mode */
2268 reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
2269 if (reg_val == -1)
2270 goto error;
2271 if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
2272 goto error;
2273
2274 alps_exit_command_mode(psmouse);
2275 return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
2276
2277error:
2278 alps_exit_command_mode(psmouse);
2279 return ret;
2280}
2281
Seth Forshee25bded72011-11-07 19:53:36 -08002282/* Must be in command mode when calling this function */
2283static int alps_absolute_mode_v4(struct psmouse *psmouse)
2284{
2285 int reg_val;
2286
2287 reg_val = alps_command_mode_read_reg(psmouse, 0x0004);
2288 if (reg_val == -1)
2289 return -1;
2290
2291 reg_val |= 0x02;
2292 if (__alps_command_mode_write_reg(psmouse, reg_val))
2293 return -1;
2294
2295 return 0;
2296}
2297
2298static int alps_hw_init_v4(struct psmouse *psmouse)
2299{
Seth Forshee25bded72011-11-07 19:53:36 -08002300 struct ps2dev *ps2dev = &psmouse->ps2dev;
2301 unsigned char param[4];
2302
Kevin Cernekeed18e53f2013-02-21 22:58:20 -08002303 if (alps_enter_command_mode(psmouse))
Seth Forshee25bded72011-11-07 19:53:36 -08002304 goto error;
2305
2306 if (alps_absolute_mode_v4(psmouse)) {
2307 psmouse_err(psmouse, "Failed to enter absolute mode\n");
2308 goto error;
2309 }
2310
2311 if (alps_command_mode_write_reg(psmouse, 0x0007, 0x8c))
2312 goto error;
2313
2314 if (alps_command_mode_write_reg(psmouse, 0x0149, 0x03))
2315 goto error;
2316
2317 if (alps_command_mode_write_reg(psmouse, 0x0160, 0x03))
2318 goto error;
2319
2320 if (alps_command_mode_write_reg(psmouse, 0x017f, 0x15))
2321 goto error;
2322
2323 if (alps_command_mode_write_reg(psmouse, 0x0151, 0x01))
2324 goto error;
2325
2326 if (alps_command_mode_write_reg(psmouse, 0x0168, 0x03))
2327 goto error;
2328
2329 if (alps_command_mode_write_reg(psmouse, 0x014a, 0x03))
2330 goto error;
2331
2332 if (alps_command_mode_write_reg(psmouse, 0x0161, 0x03))
2333 goto error;
2334
2335 alps_exit_command_mode(psmouse);
2336
2337 /*
2338 * This sequence changes the output from a 9-byte to an
2339 * 8-byte format. All the same data seems to be present,
2340 * just in a more compact format.
2341 */
2342 param[0] = 0xc8;
2343 param[1] = 0x64;
2344 param[2] = 0x50;
2345 if (ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
2346 ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE) ||
2347 ps2_command(ps2dev, &param[2], PSMOUSE_CMD_SETRATE) ||
2348 ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
2349 return -1;
2350
2351 /* Set rate and enable data reporting */
2352 param[0] = 0x64;
2353 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRATE) ||
2354 ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE)) {
2355 psmouse_err(psmouse, "Failed to enable data reporting\n");
2356 return -1;
2357 }
2358
2359 return 0;
2360
2361error:
2362 /*
2363 * Leaving the touchpad in command mode will essentially render
2364 * it unusable until the machine reboots, so exit it here just
2365 * to be safe
2366 */
2367 alps_exit_command_mode(psmouse);
2368 return -1;
2369}
2370
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002371static int alps_get_otp_values_ss4_v2(struct psmouse *psmouse,
2372 unsigned char index, unsigned char otp[])
2373{
2374 struct ps2dev *ps2dev = &psmouse->ps2dev;
2375
2376 switch (index) {
2377 case 0:
2378 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
2379 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
2380 ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
2381 return -1;
2382
2383 break;
2384
2385 case 1:
2386 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
2387 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
2388 ps2_command(ps2dev, otp, PSMOUSE_CMD_GETINFO))
2389 return -1;
2390
2391 break;
2392 }
2393
2394 return 0;
2395}
2396
Fengguang Wu07f19e32015-04-10 23:54:31 -07002397static int alps_update_device_area_ss4_v2(unsigned char otp[][4],
2398 struct alps_data *priv)
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002399{
2400 int num_x_electrode;
2401 int num_y_electrode;
2402 int x_pitch, y_pitch, x_phys, y_phys;
2403
2404 num_x_electrode = SS4_NUMSENSOR_XOFFSET + (otp[1][0] & 0x0F);
2405 num_y_electrode = SS4_NUMSENSOR_YOFFSET + ((otp[1][0] >> 4) & 0x0F);
2406
2407 priv->x_max = (num_x_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
2408 priv->y_max = (num_y_electrode - 1) * SS4_COUNT_PER_ELECTRODE;
2409
2410 x_pitch = ((otp[1][2] >> 2) & 0x07) + SS4_MIN_PITCH_MM;
2411 y_pitch = ((otp[1][2] >> 5) & 0x07) + SS4_MIN_PITCH_MM;
2412
2413 x_phys = x_pitch * (num_x_electrode - 1); /* In 0.1 mm units */
2414 y_phys = y_pitch * (num_y_electrode - 1); /* In 0.1 mm units */
2415
2416 priv->x_res = priv->x_max * 10 / x_phys; /* units / mm */
2417 priv->y_res = priv->y_max * 10 / y_phys; /* units / mm */
2418
2419 return 0;
2420}
2421
Fengguang Wu07f19e32015-04-10 23:54:31 -07002422static int alps_update_btn_info_ss4_v2(unsigned char otp[][4],
2423 struct alps_data *priv)
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002424{
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002425 unsigned char is_btnless;
2426
2427 is_btnless = (otp[1][1] >> 3) & 0x01;
2428
2429 if (is_btnless)
2430 priv->flags |= ALPS_BUTTONPAD;
2431
2432 return 0;
2433}
2434
2435static int alps_set_defaults_ss4_v2(struct psmouse *psmouse,
2436 struct alps_data *priv)
2437{
2438 unsigned char otp[2][4];
2439
2440 memset(otp, 0, sizeof(otp));
2441
2442 if (alps_get_otp_values_ss4_v2(psmouse, 0, &otp[0][0]) ||
2443 alps_get_otp_values_ss4_v2(psmouse, 1, &otp[1][0]))
2444 return -1;
2445
2446 alps_update_device_area_ss4_v2(otp, priv);
2447
2448 alps_update_btn_info_ss4_v2(otp, priv);
2449
2450 return 0;
2451}
2452
Yunkang Tangee65d4b2013-12-26 14:54:19 -08002453static int alps_dolphin_get_device_area(struct psmouse *psmouse,
2454 struct alps_data *priv)
2455{
2456 struct ps2dev *ps2dev = &psmouse->ps2dev;
2457 unsigned char param[4] = {0};
2458 int num_x_electrode, num_y_electrode;
2459
2460 if (alps_enter_command_mode(psmouse))
2461 return -1;
2462
2463 param[0] = 0x0a;
2464 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_RESET_WRAP) ||
2465 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
2466 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETPOLL) ||
2467 ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
2468 ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE))
2469 return -1;
2470
2471 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
2472 return -1;
2473
2474 /*
2475 * Dolphin's sensor line number is not fixed. It can be calculated
2476 * by adding the device's register value with DOLPHIN_PROFILE_X/YOFFSET.
2477 * Further more, we can get device's x_max and y_max by multiplying
2478 * sensor line number with DOLPHIN_COUNT_PER_ELECTRODE.
2479 *
2480 * e.g. When we get register's sensor_x = 11 & sensor_y = 8,
2481 * real sensor line number X = 11 + 8 = 19, and
2482 * real sensor line number Y = 8 + 1 = 9.
2483 * So, x_max = (19 - 1) * 64 = 1152, and
2484 * y_max = (9 - 1) * 64 = 512.
2485 */
2486 num_x_electrode = DOLPHIN_PROFILE_XOFFSET + (param[2] & 0x0F);
2487 num_y_electrode = DOLPHIN_PROFILE_YOFFSET + ((param[2] >> 4) & 0x0F);
2488 priv->x_bits = num_x_electrode;
2489 priv->y_bits = num_y_electrode;
2490 priv->x_max = (num_x_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
2491 priv->y_max = (num_y_electrode - 1) * DOLPHIN_COUNT_PER_ELECTRODE;
2492
2493 if (alps_exit_command_mode(psmouse))
2494 return -1;
2495
2496 return 0;
2497}
2498
Dave Turvene75af9e52013-02-21 22:58:28 -08002499static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
2500{
2501 struct ps2dev *ps2dev = &psmouse->ps2dev;
2502 unsigned char param[2];
2503
2504 /* This is dolphin "v1" as empirically defined by florin9doi */
2505 param[0] = 0x64;
2506 param[1] = 0x28;
2507
2508 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
2509 ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
2510 ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
2511 return -1;
2512
2513 return 0;
2514}
2515
Yunkang Tang38088432014-07-26 13:51:41 -07002516static int alps_hw_init_v7(struct psmouse *psmouse)
2517{
2518 struct ps2dev *ps2dev = &psmouse->ps2dev;
2519 int reg_val, ret = -1;
2520
2521 if (alps_enter_command_mode(psmouse) ||
2522 alps_command_mode_read_reg(psmouse, 0xc2d9) == -1)
2523 goto error;
2524
Hans de Goedef3f33c62014-07-29 11:22:07 -07002525 if (alps_get_v3_v7_resolution(psmouse, 0xc397))
2526 goto error;
2527
Yunkang Tang38088432014-07-26 13:51:41 -07002528 if (alps_command_mode_write_reg(psmouse, 0xc2c9, 0x64))
2529 goto error;
2530
2531 reg_val = alps_command_mode_read_reg(psmouse, 0xc2c4);
2532 if (reg_val == -1)
2533 goto error;
2534 if (__alps_command_mode_write_reg(psmouse, reg_val | 0x02))
2535 goto error;
2536
2537 alps_exit_command_mode(psmouse);
2538 return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
2539
2540error:
2541 alps_exit_command_mode(psmouse);
2542 return ret;
2543}
2544
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002545static int alps_hw_init_ss4_v2(struct psmouse *psmouse)
2546{
2547 struct ps2dev *ps2dev = &psmouse->ps2dev;
2548 char param[2] = {0x64, 0x28};
2549 int ret = -1;
2550
2551 /* enter absolute mode */
2552 if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
2553 ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
2554 ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
2555 ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE)) {
2556 goto error;
2557 }
2558
2559 /* T.B.D. Decread noise packet number, delete in the future */
2560 if (alps_exit_command_mode(psmouse) ||
2561 alps_enter_command_mode(psmouse) ||
2562 alps_command_mode_write_reg(psmouse, 0x001D, 0x20)) {
2563 goto error;
2564 }
2565 alps_exit_command_mode(psmouse);
2566
2567 return ps2_command(ps2dev, NULL, PSMOUSE_CMD_ENABLE);
2568
2569error:
2570 alps_exit_command_mode(psmouse);
2571 return ret;
2572}
2573
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002574static int alps_set_protocol(struct psmouse *psmouse,
2575 struct alps_data *priv,
2576 const struct alps_protocol_info *protocol)
Seth Forshee25bded72011-11-07 19:53:36 -08002577{
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002578 psmouse->private = priv;
2579
2580 setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse);
2581
2582 priv->proto_version = protocol->version;
2583 priv->byte0 = protocol->byte0;
2584 priv->mask0 = protocol->mask0;
2585 priv->flags = protocol->flags;
Kevin Cernekeef673ceb2013-02-13 22:23:34 -08002586
Kevin Cernekee7a9f73e2013-02-13 22:24:55 -08002587 priv->x_max = 2000;
2588 priv->y_max = 1400;
2589 priv->x_bits = 15;
2590 priv->y_bits = 11;
2591
Kevin Cernekee99df65e2013-02-13 20:56:33 -08002592 switch (priv->proto_version) {
Seth Forshee25bded72011-11-07 19:53:36 -08002593 case ALPS_PROTO_V1:
2594 case ALPS_PROTO_V2:
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002595 priv->hw_init = alps_hw_init_v1_v2;
2596 priv->process_packet = alps_process_packet_v1_v2;
2597 priv->set_abs_params = alps_set_abs_params_st;
Yunkang Tang95f75e92013-12-01 22:33:52 -08002598 priv->x_max = 1023;
2599 priv->y_max = 767;
Seth Forshee25bded72011-11-07 19:53:36 -08002600 break;
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -08002601
Seth Forshee25bded72011-11-07 19:53:36 -08002602 case ALPS_PROTO_V3:
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002603 priv->hw_init = alps_hw_init_v3;
2604 priv->process_packet = alps_process_packet_v3;
2605 priv->set_abs_params = alps_set_abs_params_mt;
Kevin Cernekeef85e5002013-02-13 22:26:11 -08002606 priv->decode_fields = alps_decode_pinnacle;
Kevin Cernekee50e8b212013-02-13 22:23:04 -08002607 priv->nibble_commands = alps_v3_nibble_commands;
2608 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
Seth Forshee25bded72011-11-07 19:53:36 -08002609 break;
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -08002610
2611 case ALPS_PROTO_V3_RUSHMORE:
2612 priv->hw_init = alps_hw_init_rushmore_v3;
2613 priv->process_packet = alps_process_packet_v3;
2614 priv->set_abs_params = alps_set_abs_params_mt;
2615 priv->decode_fields = alps_decode_rushmore;
2616 priv->nibble_commands = alps_v3_nibble_commands;
2617 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
2618 priv->x_bits = 16;
2619 priv->y_bits = 12;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002620
2621 if (alps_probe_trackstick_v3(psmouse,
2622 ALPS_REG_BASE_RUSHMORE) < 0)
2623 priv->flags &= ~ALPS_DUALPOINT;
2624
Dmitry Torokhovfb2dd7a2015-01-14 10:39:52 -08002625 break;
2626
Seth Forshee25bded72011-11-07 19:53:36 -08002627 case ALPS_PROTO_V4:
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002628 priv->hw_init = alps_hw_init_v4;
2629 priv->process_packet = alps_process_packet_v4;
2630 priv->set_abs_params = alps_set_abs_params_mt;
Kevin Cernekee50e8b212013-02-13 22:23:04 -08002631 priv->nibble_commands = alps_v4_nibble_commands;
2632 priv->addr_command = PSMOUSE_CMD_DISABLE;
Seth Forshee25bded72011-11-07 19:53:36 -08002633 break;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002634
Dave Turvene75af9e52013-02-21 22:58:28 -08002635 case ALPS_PROTO_V5:
2636 priv->hw_init = alps_hw_init_dolphin_v1;
Yunkang Tangee65d4b2013-12-26 14:54:19 -08002637 priv->process_packet = alps_process_touchpad_packet_v3_v5;
Dave Turvene75af9e52013-02-21 22:58:28 -08002638 priv->decode_fields = alps_decode_dolphin;
2639 priv->set_abs_params = alps_set_abs_params_mt;
2640 priv->nibble_commands = alps_v3_nibble_commands;
2641 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
Dave Turvene75af9e52013-02-21 22:58:28 -08002642 priv->x_bits = 23;
2643 priv->y_bits = 12;
Dmitry Torokhovc164c142015-03-21 20:29:34 -07002644
2645 if (alps_dolphin_get_device_area(psmouse, priv))
2646 return -EIO;
2647
Dave Turvene75af9e52013-02-21 22:58:28 -08002648 break;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002649
Yunkang Tang95f75e92013-12-01 22:33:52 -08002650 case ALPS_PROTO_V6:
2651 priv->hw_init = alps_hw_init_v6;
2652 priv->process_packet = alps_process_packet_v6;
2653 priv->set_abs_params = alps_set_abs_params_st;
2654 priv->nibble_commands = alps_v6_nibble_commands;
2655 priv->x_max = 2047;
2656 priv->y_max = 1535;
2657 break;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002658
Yunkang Tang38088432014-07-26 13:51:41 -07002659 case ALPS_PROTO_V7:
2660 priv->hw_init = alps_hw_init_v7;
2661 priv->process_packet = alps_process_packet_v7;
2662 priv->decode_fields = alps_decode_packet_v7;
Masaki Ota8eccd392015-03-27 20:44:21 -07002663 priv->set_abs_params = alps_set_abs_params_v7;
Yunkang Tang38088432014-07-26 13:51:41 -07002664 priv->nibble_commands = alps_v3_nibble_commands;
2665 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
Dmitry Torokhovc164c142015-03-21 20:29:34 -07002666 priv->x_max = 0xfff;
2667 priv->y_max = 0x7ff;
Yunkang Tang38088432014-07-26 13:51:41 -07002668
2669 if (priv->fw_ver[1] != 0xba)
2670 priv->flags |= ALPS_BUTTONPAD;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002671
Yunkang Tang38088432014-07-26 13:51:41 -07002672 break;
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002673
2674 case ALPS_PROTO_V8:
2675 priv->hw_init = alps_hw_init_ss4_v2;
2676 priv->process_packet = alps_process_packet_ss4_v2;
2677 priv->decode_fields = alps_decode_ss4_v2;
2678 priv->set_abs_params = alps_set_abs_params_ss4_v2;
2679 priv->nibble_commands = alps_v3_nibble_commands;
2680 priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
2681
2682 if (alps_set_defaults_ss4_v2(psmouse, priv))
2683 return -EIO;
2684
2685 break;
Seth Forshee25bded72011-11-07 19:53:36 -08002686 }
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002687
2688 return 0;
Seth Forshee25bded72011-11-07 19:53:36 -08002689}
2690
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002691static const struct alps_protocol_info *alps_match_table(unsigned char *e7,
2692 unsigned char *ec)
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002693{
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002694 const struct alps_model_info *model;
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002695 int i;
2696
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002697 for (i = 0; i < ARRAY_SIZE(alps_model_data); i++) {
2698 model = &alps_model_data[i];
2699
2700 if (!memcmp(e7, model->signature, sizeof(model->signature)) &&
2701 (!model->command_mode_resp ||
2702 model->command_mode_resp == ec[2])) {
2703
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002704 return &model->protocol_info;
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002705 }
2706 }
2707
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002708 return NULL;
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002709}
2710
2711static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
2712{
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002713 const struct alps_protocol_info *protocol;
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002714 unsigned char e6[4], e7[4], ec[4];
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002715 int error;
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002716
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002717 /*
2718 * First try "E6 report".
2719 * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
2720 * The bits 0-2 of the first byte will be 1s if some buttons are
2721 * pressed.
2722 */
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002723 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
2724 PSMOUSE_CMD_SETSCALE11, e6))
2725 return -EIO;
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002726
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002727 if ((e6[0] & 0xf8) != 0 || e6[1] != 0 || (e6[2] != 10 && e6[2] != 100))
2728 return -EINVAL;
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002729
2730 /*
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002731 * Now get the "E7" and "EC" reports. These will uniquely identify
2732 * most ALPS touchpads.
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002733 */
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002734 if (alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
2735 PSMOUSE_CMD_SETSCALE21, e7) ||
2736 alps_rpt_cmd(psmouse, PSMOUSE_CMD_SETRES,
2737 PSMOUSE_CMD_RESET_WRAP, ec) ||
2738 alps_exit_command_mode(psmouse))
2739 return -EIO;
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002740
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002741 protocol = alps_match_table(e7, ec);
2742 if (!protocol) {
2743 if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
2744 ec[0] == 0x73 && (ec[1] == 0x01 || ec[1] == 0x02)) {
2745 protocol = &alps_v5_protocol_data;
2746 } else if (ec[0] == 0x88 &&
2747 ((ec[1] & 0xf0) == 0xb0 || (ec[1] & 0xf0) == 0xc0)) {
2748 protocol = &alps_v7_protocol_data;
2749 } else if (ec[0] == 0x88 && ec[1] == 0x08) {
2750 protocol = &alps_v3_rushmore_data;
2751 } else if (ec[0] == 0x88 && ec[1] == 0x07 &&
2752 ec[2] >= 0x90 && ec[2] <= 0x9d) {
2753 protocol = &alps_v3_protocol_data;
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002754 } else if (e7[0] == 0x73 && e7[1] == 0x03 &&
2755 e7[2] == 0x14 && ec[1] == 0x02) {
2756 protocol = &alps_v8_protocol_data;
Dmitry Torokhov3296f712015-01-12 00:30:32 -08002757 } else {
2758 psmouse_dbg(psmouse,
2759 "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
2760 return -EINVAL;
2761 }
2762 }
2763
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002764 if (priv) {
2765 /* Save the Firmware version */
2766 memcpy(priv->fw_ver, ec, 3);
2767 error = alps_set_protocol(psmouse, priv, protocol);
2768 if (error)
2769 return error;
2770 }
Hans de Goedec0cd17f2014-07-25 22:49:14 -07002771
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002772 return 0;
Kevin Cernekee2e992cc2013-02-13 20:57:04 -08002773}
2774
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04002775static int alps_reconnect(struct psmouse *psmouse)
2776{
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002777 struct alps_data *priv = psmouse->private;
Maxim Levitsky71bb21b2009-11-16 22:12:22 -08002778
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04002779 psmouse_reset(psmouse);
2780
Kevin Cernekeeb5d6b852013-02-13 22:19:59 -08002781 if (alps_identify(psmouse, priv) < 0)
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04002782 return -1;
2783
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002784 return priv->hw_init(psmouse);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785}
2786
2787static void alps_disconnect(struct psmouse *psmouse)
2788{
2789 struct alps_data *priv = psmouse->private;
Dmitry Torokhov2e5b6362005-09-15 02:01:44 -05002790
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 psmouse_reset(psmouse);
Sebastian Kapfer1d9f2622009-12-15 08:39:50 -08002792 del_timer_sync(&priv->timer);
Pali Rohár04aae282015-01-14 13:18:30 -08002793 if (priv->dev2)
2794 input_unregister_device(priv->dev2);
2795 if (!IS_ERR_OR_NULL(priv->dev3))
2796 input_unregister_device(priv->dev3);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 kfree(priv);
2798}
2799
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002800static void alps_set_abs_params_st(struct alps_data *priv,
2801 struct input_dev *dev1)
2802{
Yunkang Tang95f75e92013-12-01 22:33:52 -08002803 input_set_abs_params(dev1, ABS_X, 0, priv->x_max, 0, 0);
2804 input_set_abs_params(dev1, ABS_Y, 0, priv->y_max, 0, 0);
Masaki Ota8eccd392015-03-27 20:44:21 -07002805 input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002806}
2807
Masaki Ota8eccd392015-03-27 20:44:21 -07002808static void alps_set_abs_params_mt_common(struct alps_data *priv,
2809 struct input_dev *dev1)
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002810{
Kevin Cernekee7a9f73e2013-02-13 22:24:55 -08002811 input_set_abs_params(dev1, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
2812 input_set_abs_params(dev1, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002813
Hans de Goedef3f33c62014-07-29 11:22:07 -07002814 input_abs_set_res(dev1, ABS_MT_POSITION_X, priv->x_res);
2815 input_abs_set_res(dev1, ABS_MT_POSITION_Y, priv->y_res);
2816
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002817 set_bit(BTN_TOOL_TRIPLETAP, dev1->keybit);
2818 set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
Masaki Ota8eccd392015-03-27 20:44:21 -07002819}
Yunkang Tang38088432014-07-26 13:51:41 -07002820
Masaki Ota8eccd392015-03-27 20:44:21 -07002821static void alps_set_abs_params_mt(struct alps_data *priv,
2822 struct input_dev *dev1)
2823{
2824 alps_set_abs_params_mt_common(priv, dev1);
2825 input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
2826
2827 input_mt_init_slots(dev1, MAX_TOUCHES,
2828 INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
2829 INPUT_MT_TRACK | INPUT_MT_SEMI_MT);
2830}
2831
2832static void alps_set_abs_params_v7(struct alps_data *priv,
2833 struct input_dev *dev1)
2834{
2835 alps_set_abs_params_mt_common(priv, dev1);
Masaki Ota8d289842015-03-27 21:30:46 -07002836 set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
Masaki Ota8eccd392015-03-27 20:44:21 -07002837
2838 input_mt_init_slots(dev1, MAX_TOUCHES,
2839 INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
2840 INPUT_MT_TRACK);
Masaki Ota3db5b9f2015-03-27 20:57:52 -07002841
2842 set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
2843}
2844
2845static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
2846 struct input_dev *dev1)
2847{
2848 alps_set_abs_params_mt_common(priv, dev1);
2849 input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
2850 set_bit(BTN_TOOL_QUINTTAP, dev1->keybit);
2851
2852 input_mt_init_slots(dev1, MAX_TOUCHES,
2853 INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
2854 INPUT_MT_TRACK);
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002855}
2856
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857int alps_init(struct psmouse *psmouse)
2858{
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002859 struct alps_data *priv = psmouse->private;
Pali Rohár04aae282015-01-14 13:18:30 -08002860 struct input_dev *dev1 = psmouse->dev;
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002861 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002863 error = priv->hw_init(psmouse);
2864 if (error)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 goto init_fail;
2866
Dmitry Torokhov7105d2e2009-12-11 23:54:54 -08002867 /*
2868 * Undo part of setup done for us by psmouse core since touchpad
2869 * is not a relative device.
2870 */
2871 __clear_bit(EV_REL, dev1->evbit);
2872 __clear_bit(REL_X, dev1->relbit);
2873 __clear_bit(REL_Y, dev1->relbit);
2874
2875 /*
2876 * Now set up our capabilities.
2877 */
Jiri Slaby7b19ada2007-10-18 23:40:32 -07002878 dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY);
2879 dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
2880 dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER);
Maxim Levitsky71bb21b2009-11-16 22:12:22 -08002881 dev1->keybit[BIT_WORD(BTN_LEFT)] |=
2882 BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
Jiri Slaby7b19ada2007-10-18 23:40:32 -07002884 dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS);
Seth Forshee25bded72011-11-07 19:53:36 -08002885
Kevin Cernekee24af5cb2013-02-13 22:22:08 -08002886 priv->set_abs_params(priv, dev1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Kevin Cernekee99df65e2013-02-13 20:56:33 -08002888 if (priv->flags & ALPS_WHEEL) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -07002889 dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL);
2890 dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891 }
2892
Kevin Cernekee99df65e2013-02-13 20:56:33 -08002893 if (priv->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -07002894 dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD);
2895 dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 }
2897
Kevin Cernekee99df65e2013-02-13 20:56:33 -08002898 if (priv->flags & ALPS_FOUR_BUTTONS) {
Maxim Levitsky71bb21b2009-11-16 22:12:22 -08002899 dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0);
2900 dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1);
2901 dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2);
2902 dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3);
Yunkang Tang38088432014-07-26 13:51:41 -07002903 } else if (priv->flags & ALPS_BUTTONPAD) {
2904 set_bit(INPUT_PROP_BUTTONPAD, dev1->propbit);
2905 clear_bit(BTN_RIGHT, dev1->keybit);
Maxim Levitsky71bb21b2009-11-16 22:12:22 -08002906 } else {
2907 dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE);
2908 }
2909
Pali Rohárdfba8602015-01-09 12:48:44 -08002910 if (priv->flags & ALPS_DUALPOINT) {
Pali Rohár04aae282015-01-14 13:18:30 -08002911 struct input_dev *dev2;
2912
2913 dev2 = input_allocate_device();
2914 if (!dev2) {
2915 psmouse_err(psmouse,
2916 "failed to allocate trackstick device\n");
2917 error = -ENOMEM;
2918 goto init_fail;
2919 }
2920
2921 snprintf(priv->phys2, sizeof(priv->phys2), "%s/input1",
2922 psmouse->ps2dev.serio->phys);
2923 dev2->phys = priv->phys2;
2924
Pali Rohárdfba8602015-01-09 12:48:44 -08002925 /*
2926 * format of input device name is: "protocol vendor name"
2927 * see function psmouse_switch_protocol() in psmouse-base.c
2928 */
2929 dev2->name = "AlpsPS/2 ALPS DualPoint Stick";
Pali Rohár04aae282015-01-14 13:18:30 -08002930
2931 dev2->id.bustype = BUS_I8042;
2932 dev2->id.vendor = 0x0002;
Pali Rohárdfba8602015-01-09 12:48:44 -08002933 dev2->id.product = PSMOUSE_ALPS;
2934 dev2->id.version = priv->proto_version;
Pali Rohár04aae282015-01-14 13:18:30 -08002935 dev2->dev.parent = &psmouse->ps2dev.serio->dev;
Pali Rohárdfba8602015-01-09 12:48:44 -08002936
Pali Rohár04aae282015-01-14 13:18:30 -08002937 input_set_capability(dev2, EV_REL, REL_X);
2938 input_set_capability(dev2, EV_REL, REL_Y);
2939 input_set_capability(dev2, EV_KEY, BTN_LEFT);
2940 input_set_capability(dev2, EV_KEY, BTN_RIGHT);
2941 input_set_capability(dev2, EV_KEY, BTN_MIDDLE);
Dmitry Torokhov968ac842005-05-29 02:28:29 -05002942
Pali Rohár04aae282015-01-14 13:18:30 -08002943 __set_bit(INPUT_PROP_POINTER, dev2->propbit);
Hans de Goede76113922014-09-08 14:42:12 -07002944 __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
2945
Pali Rohár04aae282015-01-14 13:18:30 -08002946 error = input_register_device(dev2);
2947 if (error) {
2948 psmouse_err(psmouse,
2949 "failed to register trackstick device: %d\n",
2950 error);
2951 input_free_device(dev2);
2952 goto init_fail;
2953 }
2954
2955 priv->dev2 = dev2;
2956 }
2957
2958 priv->psmouse = psmouse;
2959
2960 INIT_DELAYED_WORK(&priv->dev3_register_work,
2961 alps_register_bare_ps2_mouse);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962
2963 psmouse->protocol_handler = alps_process_byte;
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05002964 psmouse->poll = alps_poll;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 psmouse->disconnect = alps_disconnect;
2966 psmouse->reconnect = alps_reconnect;
Kevin Cernekee99df65e2013-02-13 20:56:33 -08002967 psmouse->pktsize = priv->proto_version == ALPS_PROTO_V4 ? 8 : 6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Dmitry Torokhovf0d5c6f42006-01-14 00:27:37 -05002969 /* We are having trouble resyncing ALPS touchpads so disable it for now */
2970 psmouse->resync_time = 0;
2971
Pali Rohár9d720b32014-11-08 12:58:57 -08002972 /* Allow 2 invalid packets without resetting device */
2973 psmouse->resetafter = psmouse->pktsize * 2;
2974
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 return 0;
2976
2977init_fail:
Dmitry Torokhovf42649e2007-04-12 01:31:13 -04002978 psmouse_reset(psmouse);
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002979 /*
2980 * Even though we did not allocate psmouse->private we do free
2981 * it here.
2982 */
2983 kfree(psmouse->private);
Dmitry Torokhov1e0c5b12007-05-14 23:51:54 -04002984 psmouse->private = NULL;
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002985 return error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986}
2987
Dmitry Torokhovb7802c52009-09-09 19:13:20 -07002988int alps_detect(struct psmouse *psmouse, bool set_properties)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989{
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002990 struct alps_data *priv;
2991 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992
Dmitry Torokhova09221e2015-01-13 20:46:09 -08002993 error = alps_identify(psmouse, NULL);
2994 if (error)
2995 return error;
2996
2997 /*
2998 * Reset the device to make sure it is fully operational:
2999 * on some laptops, like certain Dell Latitudes, we may
3000 * fail to properly detect presence of trackstick if device
3001 * has not been reset.
3002 */
3003 psmouse_reset(psmouse);
3004
3005 priv = kzalloc(sizeof(struct alps_data), GFP_KERNEL);
3006 if (!priv)
3007 return -ENOMEM;
3008
3009 error = alps_identify(psmouse, priv);
Dmitry Torokhov93050db2015-02-27 15:49:51 -08003010 if (error) {
3011 kfree(priv);
Dmitry Torokhova09221e2015-01-13 20:46:09 -08003012 return error;
Dmitry Torokhov93050db2015-02-27 15:49:51 -08003013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
3015 if (set_properties) {
3016 psmouse->vendor = "ALPS";
Dmitry Torokhova09221e2015-01-13 20:46:09 -08003017 psmouse->name = priv->flags & ALPS_DUALPOINT ?
Dmitry Torokhov968ac842005-05-29 02:28:29 -05003018 "DualPoint TouchPad" : "GlidePoint";
Dmitry Torokhova09221e2015-01-13 20:46:09 -08003019 psmouse->model = priv->proto_version;
3020 } else {
3021 /*
3022 * Destroy alps_data structure we allocated earlier since
3023 * this was just a "trial run". Otherwise we'll keep it
3024 * to be used by alps_init() which has to be called if
3025 * we succeed and set_properties is true.
3026 */
3027 kfree(priv);
3028 psmouse->private = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 }
Dmitry Torokhova09221e2015-01-13 20:46:09 -08003030
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 return 0;
3032}
3033