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

Input: ALPS - add interleaved protocol support (Dell E6x00 series)

Properly handle version of the protocol where standard PS/2 packets
from trackpoint are stuffed into middle (byte 3-6) of the standard
ALPS packets when both the touchpad and trackpoint are used together.

The patch is based on work done by Matthew Chapman and additional
research done by David Kubicek and Erik Osterholm:

https://bugs.launchpad.net/ubuntu/+source/linux/+bug/296610

Many thanks to David Kubicek for his efforts in researching fine points
of this new version of the protocol, especially interaction between pad
and stick in these models.

Signed-off-by: Sebastian Kapfer <sebastian_kapfer@gmx.net>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

Sebastian Kapfer and committed by
Dmitry Torokhov
1d9f2626 18f7ad59

+229 -28
+228 -28
drivers/input/mouse/alps.c
··· 5 5 * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> 6 6 * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> 7 7 * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> 8 + * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> 8 9 * 9 10 * ALPS detection, tap switching and status querying info is taken from 10 11 * tpconfig utility (by C. Scott Ananian and Bruce Kall). ··· 29 28 #define dbg(format, arg...) do {} while (0) 30 29 #endif 31 30 32 - 33 31 #define ALPS_OLDPROTO 0x01 /* old style input */ 34 32 #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ 35 33 #define ALPS_PASS 0x04 /* device has a pass-through port */ ··· 37 37 #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ 38 38 #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ 39 39 #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ 40 - 40 + #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with 41 + 6-byte ALPS packet */ 41 42 42 43 static const struct alps_model_info alps_model_data[] = { 43 44 { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ ··· 59 58 { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ 60 59 { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, 61 60 { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ 62 - { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ 61 + /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ 62 + { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, 63 + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, 63 64 { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ 64 65 }; 65 66 ··· 72 69 */ 73 70 74 71 /* 75 - * ALPS abolute Mode - new format 72 + * PS/2 packet format 73 + * 74 + * byte 0: 0 0 YSGN XSGN 1 M R L 75 + * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 76 + * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 77 + * 78 + * Note that the device never signals overflow condition. 79 + * 80 + * ALPS absolute Mode - new format 76 81 * 77 82 * byte 0: 1 ? ? ? 1 ? ? ? 78 83 * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 79 - * byte 2: 0 x10 x9 x8 x7 ? fin ges 84 + * byte 2: 0 x10 x9 x8 x7 ? fin ges 80 85 * byte 3: 0 y9 y8 y7 1 M R L 81 86 * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 82 87 * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 88 + * 89 + * Dualpoint device -- interleaved packet format 90 + * 91 + * byte 0: 1 1 0 0 1 1 1 1 92 + * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 93 + * byte 2: 0 x10 x9 x8 x7 0 fin ges 94 + * byte 3: 0 0 YSGN XSGN 1 1 1 1 95 + * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 96 + * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 97 + * byte 6: 0 y9 y8 y7 1 m r l 98 + * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 99 + * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 100 + * 101 + * CAPITALS = stick, miniscules = touchpad 83 102 * 84 103 * ?'s can have different meanings on different models, 85 104 * such as wheel rotation, extra buttons, stick buttons 86 105 * on a dualpoint, etc. 87 106 */ 107 + 108 + static bool alps_is_valid_first_byte(const struct alps_model_info *model, 109 + unsigned char data) 110 + { 111 + return (data & model->mask0) == model->byte0; 112 + } 113 + 114 + static void alps_report_buttons(struct psmouse *psmouse, 115 + struct input_dev *dev1, struct input_dev *dev2, 116 + int left, int right, int middle) 117 + { 118 + struct alps_data *priv = psmouse->private; 119 + const struct alps_model_info *model = priv->i; 120 + 121 + if (model->flags & ALPS_PS2_INTERLEAVED) { 122 + struct input_dev *dev; 123 + 124 + /* 125 + * If shared button has already been reported on the 126 + * other device (dev2) then this event should be also 127 + * sent through that device. 128 + */ 129 + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; 130 + input_report_key(dev, BTN_LEFT, left); 131 + 132 + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; 133 + input_report_key(dev, BTN_RIGHT, right); 134 + 135 + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; 136 + input_report_key(dev, BTN_MIDDLE, middle); 137 + 138 + /* 139 + * Sync the _other_ device now, we'll do the first 140 + * device later once we report the rest of the events. 141 + */ 142 + input_sync(dev2); 143 + } else { 144 + /* 145 + * For devices with non-interleaved packets we know what 146 + * device buttons belong to so we can simply report them. 147 + */ 148 + input_report_key(dev1, BTN_LEFT, left); 149 + input_report_key(dev1, BTN_RIGHT, right); 150 + input_report_key(dev1, BTN_MIDDLE, middle); 151 + } 152 + } 88 153 89 154 static void alps_process_packet(struct psmouse *psmouse) 90 155 { ··· 163 92 struct input_dev *dev2 = priv->dev2; 164 93 int x, y, z, ges, fin, left, right, middle; 165 94 int back = 0, forward = 0; 166 - 167 - if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ 168 - input_report_key(dev2, BTN_LEFT, packet[0] & 1); 169 - input_report_key(dev2, BTN_RIGHT, packet[0] & 2); 170 - input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); 171 - input_report_rel(dev2, REL_X, 172 - packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); 173 - input_report_rel(dev2, REL_Y, 174 - packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); 175 - input_sync(dev2); 176 - return; 177 - } 178 95 179 96 if (model->flags & ALPS_OLDPROTO) { 180 97 left = packet[2] & 0x10; ··· 199 140 input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); 200 141 input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); 201 142 202 - input_report_key(dev2, BTN_LEFT, left); 203 - input_report_key(dev2, BTN_RIGHT, right); 204 - input_report_key(dev2, BTN_MIDDLE, middle); 143 + alps_report_buttons(psmouse, dev2, dev, left, right, middle); 205 144 206 - input_sync(dev); 207 145 input_sync(dev2); 208 146 return; 209 147 } 210 148 211 - input_report_key(dev, BTN_LEFT, left); 212 - input_report_key(dev, BTN_RIGHT, right); 213 - input_report_key(dev, BTN_MIDDLE, middle); 149 + alps_report_buttons(psmouse, dev, dev2, left, right, middle); 214 150 215 151 /* Convert hardware tap to a reasonable Z value */ 216 152 if (ges && !fin) ··· 256 202 input_sync(dev); 257 203 } 258 204 259 - static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) 205 + static void alps_report_bare_ps2_packet(struct psmouse *psmouse, 206 + unsigned char packet[], 207 + bool report_buttons) 208 + { 209 + struct alps_data *priv = psmouse->private; 210 + struct input_dev *dev2 = priv->dev2; 211 + 212 + if (report_buttons) 213 + alps_report_buttons(psmouse, dev2, psmouse->dev, 214 + packet[0] & 1, packet[0] & 2, packet[0] & 4); 215 + 216 + input_report_rel(dev2, REL_X, 217 + packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); 218 + input_report_rel(dev2, REL_Y, 219 + packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); 220 + 221 + input_sync(dev2); 222 + } 223 + 224 + static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) 260 225 { 261 226 struct alps_data *priv = psmouse->private; 262 227 228 + if (psmouse->pktcnt < 6) 229 + return PSMOUSE_GOOD_DATA; 230 + 231 + if (psmouse->pktcnt == 6) { 232 + /* 233 + * Start a timer to flush the packet if it ends up last 234 + * 6-byte packet in the stream. Timer needs to fire 235 + * psmouse core times out itself. 20 ms should be enough 236 + * to decide if we are getting more data or not. 237 + */ 238 + mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); 239 + return PSMOUSE_GOOD_DATA; 240 + } 241 + 242 + del_timer(&priv->timer); 243 + 244 + if (psmouse->packet[6] & 0x80) { 245 + 246 + /* 247 + * Highest bit is set - that means we either had 248 + * complete ALPS packet and this is start of the 249 + * next packet or we got garbage. 250 + */ 251 + 252 + if (((psmouse->packet[3] | 253 + psmouse->packet[4] | 254 + psmouse->packet[5]) & 0x80) || 255 + (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { 256 + dbg("refusing packet %x %x %x %x " 257 + "(suspected interleaved ps/2)\n", 258 + psmouse->packet[3], psmouse->packet[4], 259 + psmouse->packet[5], psmouse->packet[6]); 260 + return PSMOUSE_BAD_DATA; 261 + } 262 + 263 + alps_process_packet(psmouse); 264 + 265 + /* Continue with the next packet */ 266 + psmouse->packet[0] = psmouse->packet[6]; 267 + psmouse->pktcnt = 1; 268 + 269 + } else { 270 + 271 + /* 272 + * High bit is 0 - that means that we indeed got a PS/2 273 + * packet in the middle of ALPS packet. 274 + * 275 + * There is also possibility that we got 6-byte ALPS 276 + * packet followed by 3-byte packet from trackpoint. We 277 + * can not distinguish between these 2 scenarios but 278 + * becase the latter is unlikely to happen in course of 279 + * normal operation (user would need to press all 280 + * buttons on the pad and start moving trackpoint 281 + * without touching the pad surface) we assume former. 282 + * Even if we are wrong the wost thing that would happen 283 + * the cursor would jump but we should not get protocol 284 + * desynchronization. 285 + */ 286 + 287 + alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], 288 + false); 289 + 290 + /* 291 + * Continue with the standard ALPS protocol handling, 292 + * but make sure we won't process it as an interleaved 293 + * packet again, which may happen if all buttons are 294 + * pressed. To avoid this let's reset the 4th bit which 295 + * is normally 1. 296 + */ 297 + psmouse->packet[3] = psmouse->packet[6] & 0xf7; 298 + psmouse->pktcnt = 4; 299 + } 300 + 301 + return PSMOUSE_GOOD_DATA; 302 + } 303 + 304 + static void alps_flush_packet(unsigned long data) 305 + { 306 + struct psmouse *psmouse = (struct psmouse *)data; 307 + 308 + serio_pause_rx(psmouse->ps2dev.serio); 309 + 310 + if (psmouse->pktcnt == 6) { 311 + 312 + /* 313 + * We did not any more data in reasonable amount of time. 314 + * Validate the last 3 bytes and process as a standard 315 + * ALPS packet. 316 + */ 317 + if ((psmouse->packet[3] | 318 + psmouse->packet[4] | 319 + psmouse->packet[5]) & 0x80) { 320 + dbg("refusing packet %x %x %x " 321 + "(suspected interleaved ps/2)\n", 322 + psmouse->packet[3], psmouse->packet[4], 323 + psmouse->packet[5]); 324 + } else { 325 + alps_process_packet(psmouse); 326 + } 327 + psmouse->pktcnt = 0; 328 + } 329 + 330 + serio_continue_rx(psmouse->ps2dev.serio); 331 + } 332 + 333 + static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) 334 + { 335 + struct alps_data *priv = psmouse->private; 336 + const struct alps_model_info *model = priv->i; 337 + 263 338 if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ 264 339 if (psmouse->pktcnt == 3) { 265 - alps_process_packet(psmouse); 340 + alps_report_bare_ps2_packet(psmouse, psmouse->packet, 341 + true); 266 342 return PSMOUSE_FULL_PACKET; 267 343 } 268 344 return PSMOUSE_GOOD_DATA; 269 345 } 270 346 271 - if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) 347 + /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ 348 + 349 + if ((model->flags & ALPS_PS2_INTERLEAVED) && 350 + psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { 351 + return alps_handle_interleaved_ps2(psmouse); 352 + } 353 + 354 + if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { 355 + dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", 356 + psmouse->packet[0], model->mask0, model->byte0); 272 357 return PSMOUSE_BAD_DATA; 358 + } 273 359 274 360 /* Bytes 2 - 6 should have 0 in the highest bit */ 275 361 if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && 276 - (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) 362 + (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { 363 + dbg("refusing packet[%i] = %x\n", 364 + psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); 277 365 return PSMOUSE_BAD_DATA; 366 + } 278 367 279 368 if (psmouse->pktcnt == 6) { 280 369 alps_process_packet(psmouse); ··· 656 459 struct alps_data *priv = psmouse->private; 657 460 658 461 psmouse_reset(psmouse); 462 + del_timer_sync(&priv->timer); 659 463 input_unregister_device(priv->dev2); 660 464 kfree(priv); 661 465 } ··· 674 476 goto init_fail; 675 477 676 478 priv->dev2 = dev2; 479 + setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); 480 + 677 481 psmouse->private = priv; 678 482 679 483 model = alps_get_model(psmouse, &version);
+1
drivers/input/mouse/alps.h
··· 23 23 char phys[32]; /* Phys */ 24 24 const struct alps_model_info *i;/* Info */ 25 25 int prev_fin; /* Finger bit from previous packet */ 26 + struct timer_list timer; 26 27 }; 27 28 28 29 #ifdef CONFIG_MOUSE_PS2_ALPS