aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2016-10-04 14:33:25 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2016-10-04 14:46:41 -0400
commit4777ac220c430173e297237b896932ed5fd8aaf3 (patch)
tree86fde151cee555985888c9b1aa8578accb2a1580 /drivers/input
parentf9a703a54d16ba2470391c4b12236ee56591d50c (diff)
Input: ALPS - add touchstick support for SS5 hardware
Add touchstick support for the so-called SS5 hardware, which uses a variant of the SS4 protocol. Reviewed-by: Pali Rohár <pali.rohar@gmail.com> Tested-by: Michal Hocko <mhocko@suse.com> Signed-off-by: Ben Gamari <ben@smart-cactus.org> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/mouse/alps.c65
-rw-r--r--drivers/input/mouse/alps.h2
2 files changed, 56 insertions, 11 deletions
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 936f07a4e35f..8e15783d2932 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -1156,15 +1156,28 @@ static unsigned char alps_get_pkt_id_ss4_v2(unsigned char *byte)
1156{ 1156{
1157 unsigned char pkt_id = SS4_PACKET_ID_IDLE; 1157 unsigned char pkt_id = SS4_PACKET_ID_IDLE;
1158 1158
1159 if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 && 1159 switch (byte[3] & 0x30) {
1160 (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 && byte[5] == 0x00) { 1160 case 0x00:
1161 pkt_id = SS4_PACKET_ID_IDLE; 1161 if (byte[0] == 0x18 && byte[1] == 0x10 && byte[2] == 0x00 &&
1162 } else if (!(byte[3] & 0x10)) { 1162 (byte[3] & 0x88) == 0x08 && byte[4] == 0x10 &&
1163 pkt_id = SS4_PACKET_ID_ONE; 1163 byte[5] == 0x00) {
1164 } else if (!(byte[3] & 0x20)) { 1164 pkt_id = SS4_PACKET_ID_IDLE;
1165 } else {
1166 pkt_id = SS4_PACKET_ID_ONE;
1167 }
1168 break;
1169 case 0x10:
1170 /* two-finger finger positions */
1165 pkt_id = SS4_PACKET_ID_TWO; 1171 pkt_id = SS4_PACKET_ID_TWO;
1166 } else { 1172 break;
1173 case 0x20:
1174 /* stick pointer */
1175 pkt_id = SS4_PACKET_ID_STICK;
1176 break;
1177 case 0x30:
1178 /* third and fourth finger positions */
1167 pkt_id = SS4_PACKET_ID_MULTI; 1179 pkt_id = SS4_PACKET_ID_MULTI;
1180 break;
1168 } 1181 }
1169 1182
1170 return pkt_id; 1183 return pkt_id;
@@ -1246,16 +1259,38 @@ static int alps_decode_ss4_v2(struct alps_fields *f,
1246 } 1259 }
1247 break; 1260 break;
1248 1261
1262 case SS4_PACKET_ID_STICK:
1263 if (!(priv->flags & ALPS_DUALPOINT)) {
1264 psmouse_warn(psmouse,
1265 "Rejected trackstick packet from non DualPoint device");
1266 } else {
1267 int x = (s8)(((p[0] & 1) << 7) | (p[1] & 0x7f));
1268 int y = (s8)(((p[3] & 1) << 7) | (p[2] & 0x7f));
1269
1270 input_report_rel(priv->dev2, REL_X, x);
1271 input_report_rel(priv->dev2, REL_Y, -y);
1272 }
1273 break;
1274
1249 case SS4_PACKET_ID_IDLE: 1275 case SS4_PACKET_ID_IDLE:
1250 default: 1276 default:
1251 memset(f, 0, sizeof(struct alps_fields)); 1277 memset(f, 0, sizeof(struct alps_fields));
1252 break; 1278 break;
1253 } 1279 }
1254 1280
1255 f->left = !!(SS4_BTN_V2(p) & 0x01); 1281 /* handle buttons */
1256 if (!(priv->flags & ALPS_BUTTONPAD)) { 1282 if (pkt_id == SS4_PACKET_ID_STICK) {
1257 f->right = !!(SS4_BTN_V2(p) & 0x02); 1283 f->ts_left = !!(SS4_BTN_V2(p) & 0x01);
1258 f->middle = !!(SS4_BTN_V2(p) & 0x04); 1284 if (!(priv->flags & ALPS_BUTTONPAD)) {
1285 f->ts_right = !!(SS4_BTN_V2(p) & 0x02);
1286 f->ts_middle = !!(SS4_BTN_V2(p) & 0x04);
1287 }
1288 } else {
1289 f->left = !!(SS4_BTN_V2(p) & 0x01);
1290 if (!(priv->flags & ALPS_BUTTONPAD)) {
1291 f->right = !!(SS4_BTN_V2(p) & 0x02);
1292 f->middle = !!(SS4_BTN_V2(p) & 0x04);
1293 }
1259 } 1294 }
1260 1295
1261 return 0; 1296 return 0;
@@ -1266,6 +1301,7 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
1266 struct alps_data *priv = psmouse->private; 1301 struct alps_data *priv = psmouse->private;
1267 unsigned char *packet = psmouse->packet; 1302 unsigned char *packet = psmouse->packet;
1268 struct input_dev *dev = psmouse->dev; 1303 struct input_dev *dev = psmouse->dev;
1304 struct input_dev *dev2 = priv->dev2;
1269 struct alps_fields *f = &priv->f; 1305 struct alps_fields *f = &priv->f;
1270 1306
1271 memset(f, 0, sizeof(struct alps_fields)); 1307 memset(f, 0, sizeof(struct alps_fields));
@@ -1311,6 +1347,13 @@ static void alps_process_packet_ss4_v2(struct psmouse *psmouse)
1311 1347
1312 input_report_abs(dev, ABS_PRESSURE, f->pressure); 1348 input_report_abs(dev, ABS_PRESSURE, f->pressure);
1313 input_sync(dev); 1349 input_sync(dev);
1350
1351 if (priv->flags & ALPS_DUALPOINT) {
1352 input_report_key(dev2, BTN_LEFT, f->ts_left);
1353 input_report_key(dev2, BTN_RIGHT, f->ts_right);
1354 input_report_key(dev2, BTN_MIDDLE, f->ts_middle);
1355 input_sync(dev2);
1356 }
1314} 1357}
1315 1358
1316static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse) 1359static bool alps_is_valid_package_ss4_v2(struct psmouse *psmouse)
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
index d37f814dc447..b9417e2d7ad3 100644
--- a/drivers/input/mouse/alps.h
+++ b/drivers/input/mouse/alps.h
@@ -37,12 +37,14 @@
37 * or there's button activities. 37 * or there's button activities.
38 * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad 38 * SS4_PACKET_ID_TWO: There's two or more fingers on touchpad
39 * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad 39 * SS4_PACKET_ID_MULTI: There's three or more fingers on touchpad
40 * SS4_PACKET_ID_STICK: A stick pointer packet
40*/ 41*/
41enum SS4_PACKET_ID { 42enum SS4_PACKET_ID {
42 SS4_PACKET_ID_IDLE = 0, 43 SS4_PACKET_ID_IDLE = 0,
43 SS4_PACKET_ID_ONE, 44 SS4_PACKET_ID_ONE,
44 SS4_PACKET_ID_TWO, 45 SS4_PACKET_ID_TWO,
45 SS4_PACKET_ID_MULTI, 46 SS4_PACKET_ID_MULTI,
47 SS4_PACKET_ID_STICK,
46}; 48};
47 49
48#define SS4_COUNT_PER_ELECTRODE 256 50#define SS4_COUNT_PER_ELECTRODE 256