1 /* 2 * Focaltech TouchPad PS/2 mouse driver 3 * 4 * Copyright (c) 2014 Red Hat Inc. 5 * Copyright (c) 2014 Mathias Gottschlag <mgottschlag@gmail.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * Red Hat authors: 13 * 14 * Hans de Goede <hdegoede@redhat.com> 15 */ 16 17 18 #include <linux/device.h> 19 #include <linux/libps2.h> 20 #include <linux/input/mt.h> 21 #include <linux/serio.h> 22 #include <linux/slab.h> 23 #include "psmouse.h" 24 #include "focaltech.h" 25 26 static const char * const focaltech_pnp_ids[] = { 27 "FLT0101", 28 "FLT0102", 29 "FLT0103", 30 NULL 31 }; 32 33 /* 34 * Even if the kernel is built without support for Focaltech PS/2 touchpads (or 35 * when the real driver fails to recognize the device), we still have to detect 36 * them in order to avoid further detection attempts confusing the touchpad. 37 * This way it at least works in PS/2 mouse compatibility mode. 38 */ 39 int focaltech_detect(struct psmouse *psmouse, bool set_properties) 40 { 41 if (!psmouse_matches_pnp_id(psmouse, focaltech_pnp_ids)) 42 return -ENODEV; 43 44 if (set_properties) { 45 psmouse->vendor = "FocalTech"; 46 psmouse->name = "FocalTech Touchpad"; 47 } 48 49 return 0; 50 } 51 52 static void focaltech_reset(struct psmouse *psmouse) 53 { 54 ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); 55 psmouse_reset(psmouse); 56 } 57 58 #ifdef CONFIG_MOUSE_PS2_FOCALTECH 59 60 /* 61 * Packet types - the numbers are not consecutive, so we might be missing 62 * something here. 63 */ 64 #define FOC_TOUCH 0x3 /* bitmap of active fingers */ 65 #define FOC_ABS 0x6 /* absolute position of one finger */ 66 #define FOC_REL 0x9 /* relative position of 1-2 fingers */ 67 68 #define FOC_MAX_FINGERS 5 69 70 /* 71 * Current state of a single finger on the touchpad. 72 */ 73 struct focaltech_finger_state { 74 /* The touchpad has generated a touch event for the finger */ 75 bool active; 76 77 /* 78 * The touchpad has sent position data for the finger. The 79 * flag is 0 when the finger is not active, and there is a 80 * time between the first touch event for the finger and the 81 * following absolute position packet for the finger where the 82 * touchpad has declared the finger to be valid, but we do not 83 * have any valid position yet. 84 */ 85 bool valid; 86 87 /* 88 * Absolute position (from the bottom left corner) of the 89 * finger. 90 */ 91 unsigned int x; 92 unsigned int y; 93 }; 94 95 /* 96 * Description of the current state of the touchpad hardware. 97 */ 98 struct focaltech_hw_state { 99 /* 100 * The touchpad tracks the positions of the fingers for us, 101 * the array indices correspond to the finger indices returned 102 * in the report packages. 103 */ 104 struct focaltech_finger_state fingers[FOC_MAX_FINGERS]; 105 106 /* True if the clickpad has been pressed. */ 107 bool pressed; 108 }; 109 110 struct focaltech_data { 111 unsigned int x_max, y_max; 112 struct focaltech_hw_state state; 113 }; 114 115 static void focaltech_report_state(struct psmouse *psmouse) 116 { 117 struct focaltech_data *priv = psmouse->private; 118 struct focaltech_hw_state *state = &priv->state; 119 struct input_dev *dev = psmouse->dev; 120 int i; 121 122 for (i = 0; i < FOC_MAX_FINGERS; i++) { 123 struct focaltech_finger_state *finger = &state->fingers[i]; 124 bool active = finger->active && finger->valid; 125 126 input_mt_slot(dev, i); 127 input_mt_report_slot_state(dev, MT_TOOL_FINGER, active); 128 if (active) { 129 unsigned int clamped_x, clamped_y; 130 /* 131 * The touchpad might report invalid data, so we clamp 132 * the resulting values so that we do not confuse 133 * userspace. 134 */ 135 clamped_x = clamp(finger->x, 0U, priv->x_max); 136 clamped_y = clamp(finger->y, 0U, priv->y_max); 137 input_report_abs(dev, ABS_MT_POSITION_X, clamped_x); 138 input_report_abs(dev, ABS_MT_POSITION_Y, 139 priv->y_max - clamped_y); 140 } 141 } 142 input_mt_report_pointer_emulation(dev, true); 143 144 input_report_key(psmouse->dev, BTN_LEFT, state->pressed); 145 input_sync(psmouse->dev); 146 } 147 148 static void focaltech_process_touch_packet(struct psmouse *psmouse, 149 unsigned char *packet) 150 { 151 struct focaltech_data *priv = psmouse->private; 152 struct focaltech_hw_state *state = &priv->state; 153 unsigned char fingers = packet[1]; 154 int i; 155 156 state->pressed = (packet[0] >> 4) & 1; 157 158 /* the second byte contains a bitmap of all fingers touching the pad */ 159 for (i = 0; i < FOC_MAX_FINGERS; i++) { 160 state->fingers[i].active = fingers & 0x1; 161 if (!state->fingers[i].active) { 162 /* 163 * Even when the finger becomes active again, we still 164 * will have to wait for the first valid position. 165 */ 166 state->fingers[i].valid = false; 167 } 168 fingers >>= 1; 169 } 170 } 171 172 static void focaltech_process_abs_packet(struct psmouse *psmouse, 173 unsigned char *packet) 174 { 175 struct focaltech_data *priv = psmouse->private; 176 struct focaltech_hw_state *state = &priv->state; 177 unsigned int finger; 178 179 finger = (packet[1] >> 4) - 1; 180 if (finger >= FOC_MAX_FINGERS) { 181 psmouse_err(psmouse, "Invalid finger in abs packet: %d\n", 182 finger); 183 return; 184 } 185 186 state->pressed = (packet[0] >> 4) & 1; 187 188 /* 189 * packet[5] contains some kind of tool size in the most 190 * significant nibble. 0xff is a special value (latching) that 191 * signals a large contact area. 192 */ 193 if (packet[5] == 0xff) { 194 state->fingers[finger].valid = false; 195 return; 196 } 197 198 state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2]; 199 state->fingers[finger].y = (packet[3] << 8) | packet[4]; 200 state->fingers[finger].valid = true; 201 } 202 203 static void focaltech_process_rel_packet(struct psmouse *psmouse, 204 unsigned char *packet) 205 { 206 struct focaltech_data *priv = psmouse->private; 207 struct focaltech_hw_state *state = &priv->state; 208 int finger1, finger2; 209 210 state->pressed = packet[0] >> 7; 211 finger1 = ((packet[0] >> 4) & 0x7) - 1; 212 if (finger1 < FOC_MAX_FINGERS) { 213 state->fingers[finger1].x += (char)packet[1]; 214 state->fingers[finger1].y += (char)packet[2]; 215 } else { 216 psmouse_err(psmouse, "First finger in rel packet invalid: %d\n", 217 finger1); 218 } 219 220 /* 221 * If there is an odd number of fingers, the last relative 222 * packet only contains one finger. In this case, the second 223 * finger index in the packet is 0 (we subtract 1 in the lines 224 * above to create array indices, so the finger will overflow 225 * and be above FOC_MAX_FINGERS). 226 */ 227 finger2 = ((packet[3] >> 4) & 0x7) - 1; 228 if (finger2 < FOC_MAX_FINGERS) { 229 state->fingers[finger2].x += (char)packet[4]; 230 state->fingers[finger2].y += (char)packet[5]; 231 } 232 } 233 234 static void focaltech_process_packet(struct psmouse *psmouse) 235 { 236 unsigned char *packet = psmouse->packet; 237 238 switch (packet[0] & 0xf) { 239 case FOC_TOUCH: 240 focaltech_process_touch_packet(psmouse, packet); 241 break; 242 243 case FOC_ABS: 244 focaltech_process_abs_packet(psmouse, packet); 245 break; 246 247 case FOC_REL: 248 focaltech_process_rel_packet(psmouse, packet); 249 break; 250 251 default: 252 psmouse_err(psmouse, "Unknown packet type: %02x\n", packet[0]); 253 break; 254 } 255 256 focaltech_report_state(psmouse); 257 } 258 259 static psmouse_ret_t focaltech_process_byte(struct psmouse *psmouse) 260 { 261 if (psmouse->pktcnt >= 6) { /* Full packet received */ 262 focaltech_process_packet(psmouse); 263 return PSMOUSE_FULL_PACKET; 264 } 265 266 /* 267 * We might want to do some validation of the data here, but 268 * we do not know the protocol well enough 269 */ 270 return PSMOUSE_GOOD_DATA; 271 } 272 273 static int focaltech_switch_protocol(struct psmouse *psmouse) 274 { 275 struct ps2dev *ps2dev = &psmouse->ps2dev; 276 unsigned char param[3]; 277 278 param[0] = 0; 279 if (ps2_command(ps2dev, param, 0x10f8)) 280 return -EIO; 281 282 if (ps2_command(ps2dev, param, 0x10f8)) 283 return -EIO; 284 285 if (ps2_command(ps2dev, param, 0x10f8)) 286 return -EIO; 287 288 param[0] = 1; 289 if (ps2_command(ps2dev, param, 0x10f8)) 290 return -EIO; 291 292 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11)) 293 return -EIO; 294 295 if (ps2_command(ps2dev, param, PSMOUSE_CMD_ENABLE)) 296 return -EIO; 297 298 return 0; 299 } 300 301 static void focaltech_disconnect(struct psmouse *psmouse) 302 { 303 focaltech_reset(psmouse); 304 kfree(psmouse->private); 305 psmouse->private = NULL; 306 } 307 308 static int focaltech_reconnect(struct psmouse *psmouse) 309 { 310 int error; 311 312 focaltech_reset(psmouse); 313 314 error = focaltech_switch_protocol(psmouse); 315 if (error) { 316 psmouse_err(psmouse, "Unable to initialize the device\n"); 317 return error; 318 } 319 320 return 0; 321 } 322 323 static void focaltech_set_input_params(struct psmouse *psmouse) 324 { 325 struct input_dev *dev = psmouse->dev; 326 struct focaltech_data *priv = psmouse->private; 327 328 /* 329 * Undo part of setup done for us by psmouse core since touchpad 330 * is not a relative device. 331 */ 332 __clear_bit(EV_REL, dev->evbit); 333 __clear_bit(REL_X, dev->relbit); 334 __clear_bit(REL_Y, dev->relbit); 335 __clear_bit(BTN_RIGHT, dev->keybit); 336 __clear_bit(BTN_MIDDLE, dev->keybit); 337 338 /* 339 * Now set up our capabilities. 340 */ 341 __set_bit(EV_ABS, dev->evbit); 342 input_set_abs_params(dev, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0); 343 input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0); 344 input_mt_init_slots(dev, 5, INPUT_MT_POINTER); 345 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); 346 } 347 348 static int focaltech_read_register(struct ps2dev *ps2dev, int reg, 349 unsigned char *param) 350 { 351 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETSCALE11)) 352 return -EIO; 353 354 param[0] = 0; 355 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) 356 return -EIO; 357 358 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) 359 return -EIO; 360 361 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) 362 return -EIO; 363 364 param[0] = reg; 365 if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES)) 366 return -EIO; 367 368 if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO)) 369 return -EIO; 370 371 return 0; 372 } 373 374 static int focaltech_read_size(struct psmouse *psmouse) 375 { 376 struct ps2dev *ps2dev = &psmouse->ps2dev; 377 struct focaltech_data *priv = psmouse->private; 378 char param[3]; 379 380 if (focaltech_read_register(ps2dev, 2, param)) 381 return -EIO; 382 383 /* not sure whether this is 100% correct */ 384 priv->x_max = (unsigned char)param[1] * 128; 385 priv->y_max = (unsigned char)param[2] * 128; 386 387 return 0; 388 } 389 int focaltech_init(struct psmouse *psmouse) 390 { 391 struct focaltech_data *priv; 392 int error; 393 394 psmouse->private = priv = kzalloc(sizeof(struct focaltech_data), 395 GFP_KERNEL); 396 if (!priv) 397 return -ENOMEM; 398 399 focaltech_reset(psmouse); 400 401 error = focaltech_read_size(psmouse); 402 if (error) { 403 psmouse_err(psmouse, 404 "Unable to read the size of the touchpad\n"); 405 goto fail; 406 } 407 408 error = focaltech_switch_protocol(psmouse); 409 if (error) { 410 psmouse_err(psmouse, "Unable to initialize the device\n"); 411 goto fail; 412 } 413 414 focaltech_set_input_params(psmouse); 415 416 psmouse->protocol_handler = focaltech_process_byte; 417 psmouse->pktsize = 6; 418 psmouse->disconnect = focaltech_disconnect; 419 psmouse->reconnect = focaltech_reconnect; 420 psmouse->cleanup = focaltech_reset; 421 /* resync is not supported yet */ 422 psmouse->resync_time = 0; 423 424 return 0; 425 426 fail: 427 focaltech_reset(psmouse); 428 kfree(priv); 429 return error; 430 } 431 432 #else /* CONFIG_MOUSE_PS2_FOCALTECH */ 433 434 int focaltech_init(struct psmouse *psmouse) 435 { 436 focaltech_reset(psmouse); 437 438 return 0; 439 } 440 441 #endif /* CONFIG_MOUSE_PS2_FOCALTECH */ 442