1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Stephen Evanchik <evanchsa@gmail.com> 4 * 5 * Trademarks are the property of their respective owners. 6 */ 7 8 #include <linux/array_size.h> 9 #include <linux/slab.h> 10 #include <linux/delay.h> 11 #include <linux/serio.h> 12 #include <linux/module.h> 13 #include <linux/input.h> 14 #include <linux/libps2.h> 15 #include <linux/proc_fs.h> 16 #include <linux/string.h> 17 #include <linux/uaccess.h> 18 #include "psmouse.h" 19 #include "trackpoint.h" 20 21 static const char * const trackpoint_variants[] = { 22 [TP_VARIANT_IBM] = "IBM", 23 [TP_VARIANT_ALPS] = "ALPS", 24 [TP_VARIANT_ELAN] = "Elan", 25 [TP_VARIANT_NXP] = "NXP", 26 [TP_VARIANT_JYT_SYNAPTICS] = "JYT_Synaptics", 27 [TP_VARIANT_SYNAPTICS] = "Synaptics", 28 }; 29 30 /* 31 * Power-on Reset: Resets all trackpoint parameters, including RAM values, 32 * to defaults. 33 * Returns zero on success, non-zero on failure. 34 */ 35 static int trackpoint_power_on_reset(struct ps2dev *ps2dev) 36 { 37 u8 param[2] = { TP_POR }; 38 int err; 39 40 err = ps2_command(ps2dev, param, MAKE_PS2_CMD(1, 2, TP_COMMAND)); 41 if (err) 42 return err; 43 44 /* Check for success response -- 0xAA00 */ 45 if (param[0] != 0xAA || param[1] != 0x00) 46 return -ENODEV; 47 48 return 0; 49 } 50 51 /* 52 * Device IO: read, write and toggle bit 53 */ 54 static int trackpoint_read(struct ps2dev *ps2dev, u8 loc, u8 *results) 55 { 56 results[0] = loc; 57 58 return ps2_command(ps2dev, results, MAKE_PS2_CMD(1, 1, TP_COMMAND)); 59 } 60 61 static int trackpoint_write(struct ps2dev *ps2dev, u8 loc, u8 val) 62 { 63 u8 param[3] = { TP_WRITE_MEM, loc, val }; 64 65 return ps2_command(ps2dev, param, MAKE_PS2_CMD(3, 0, TP_COMMAND)); 66 } 67 68 static int trackpoint_toggle_bit(struct ps2dev *ps2dev, u8 loc, u8 mask) 69 { 70 u8 param[3] = { TP_TOGGLE, loc, mask }; 71 72 /* Bad things will happen if the loc param isn't in this range */ 73 if (loc < 0x20 || loc >= 0x2F) 74 return -EINVAL; 75 76 return ps2_command(ps2dev, param, MAKE_PS2_CMD(3, 0, TP_COMMAND)); 77 } 78 79 static int trackpoint_update_bit(struct ps2dev *ps2dev, 80 u8 loc, u8 mask, u8 value) 81 { 82 int retval; 83 u8 data; 84 85 retval = trackpoint_read(ps2dev, loc, &data); 86 if (retval) 87 return retval; 88 89 if (((data & mask) == mask) != !!value) 90 retval = trackpoint_toggle_bit(ps2dev, loc, mask); 91 92 return retval; 93 } 94 95 /* 96 * Trackpoint-specific attributes 97 */ 98 struct trackpoint_attr_data { 99 size_t field_offset; 100 u8 command; 101 u8 mask; 102 bool inverted; 103 u8 power_on_default; 104 }; 105 106 static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, 107 void *data, char *buf) 108 { 109 struct trackpoint_data *tp = psmouse->private; 110 struct trackpoint_attr_data *attr = data; 111 u8 value = *(u8 *)((void *)tp + attr->field_offset); 112 113 if (attr->inverted) 114 value = !value; 115 116 return sprintf(buf, "%u\n", value); 117 } 118 119 static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, 120 const char *buf, size_t count) 121 { 122 struct trackpoint_data *tp = psmouse->private; 123 struct trackpoint_attr_data *attr = data; 124 u8 *field = (void *)tp + attr->field_offset; 125 u8 value; 126 int err; 127 128 err = kstrtou8(buf, 10, &value); 129 if (err) 130 return err; 131 132 *field = value; 133 err = trackpoint_write(&psmouse->ps2dev, attr->command, value); 134 135 return err ?: count; 136 } 137 138 #define TRACKPOINT_INT_ATTR(_name, _command, _default) \ 139 static struct trackpoint_attr_data trackpoint_attr_##_name = { \ 140 .field_offset = offsetof(struct trackpoint_data, _name), \ 141 .command = _command, \ 142 .power_on_default = _default, \ 143 }; \ 144 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ 145 &trackpoint_attr_##_name, \ 146 trackpoint_show_int_attr, trackpoint_set_int_attr) 147 148 static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, 149 const char *buf, size_t count) 150 { 151 struct trackpoint_data *tp = psmouse->private; 152 struct trackpoint_attr_data *attr = data; 153 bool *field = (void *)tp + attr->field_offset; 154 bool value; 155 int err; 156 157 err = kstrtobool(buf, &value); 158 if (err) 159 return err; 160 161 if (attr->inverted) 162 value = !value; 163 164 if (*field != value) { 165 *field = value; 166 err = trackpoint_toggle_bit(&psmouse->ps2dev, 167 attr->command, attr->mask); 168 } 169 170 return err ?: count; 171 } 172 173 174 #define TRACKPOINT_BIT_ATTR(_name, _command, _mask, _inv, _default) \ 175 static struct trackpoint_attr_data trackpoint_attr_##_name = { \ 176 .field_offset = offsetof(struct trackpoint_data, \ 177 _name), \ 178 .command = _command, \ 179 .mask = _mask, \ 180 .inverted = _inv, \ 181 .power_on_default = _default, \ 182 }; \ 183 PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ 184 &trackpoint_attr_##_name, \ 185 trackpoint_show_int_attr, trackpoint_set_bit_attr) 186 187 TRACKPOINT_INT_ATTR(sensitivity, TP_SENS, TP_DEF_SENS); 188 TRACKPOINT_INT_ATTR(speed, TP_SPEED, TP_DEF_SPEED); 189 TRACKPOINT_INT_ATTR(inertia, TP_INERTIA, TP_DEF_INERTIA); 190 TRACKPOINT_INT_ATTR(reach, TP_REACH, TP_DEF_REACH); 191 TRACKPOINT_INT_ATTR(draghys, TP_DRAGHYS, TP_DEF_DRAGHYS); 192 TRACKPOINT_INT_ATTR(mindrag, TP_MINDRAG, TP_DEF_MINDRAG); 193 TRACKPOINT_INT_ATTR(thresh, TP_THRESH, TP_DEF_THRESH); 194 TRACKPOINT_INT_ATTR(upthresh, TP_UP_THRESH, TP_DEF_UP_THRESH); 195 TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME, TP_DEF_Z_TIME); 196 TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV, TP_DEF_JENKS_CURV); 197 TRACKPOINT_INT_ATTR(drift_time, TP_DRIFT_TIME, TP_DEF_DRIFT_TIME); 198 199 TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, false, 200 TP_DEF_PTSON); 201 TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, false, 202 TP_DEF_SKIPBACK); 203 TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, true, 204 TP_DEF_EXT_DEV); 205 206 static bool trackpoint_is_attr_available(struct psmouse *psmouse, 207 struct attribute *attr) 208 { 209 struct trackpoint_data *tp = psmouse->private; 210 211 return tp->variant_id == TP_VARIANT_IBM || 212 attr == &psmouse_attr_sensitivity.dattr.attr || 213 attr == &psmouse_attr_press_to_select.dattr.attr; 214 } 215 216 static umode_t trackpoint_is_attr_visible(struct kobject *kobj, 217 struct attribute *attr, int n) 218 { 219 struct device *dev = kobj_to_dev(kobj); 220 struct serio *serio = to_serio_port(dev); 221 struct psmouse *psmouse = psmouse_from_serio(serio); 222 223 return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0; 224 } 225 226 static struct attribute *trackpoint_attrs[] = { 227 &psmouse_attr_sensitivity.dattr.attr, 228 &psmouse_attr_speed.dattr.attr, 229 &psmouse_attr_inertia.dattr.attr, 230 &psmouse_attr_reach.dattr.attr, 231 &psmouse_attr_draghys.dattr.attr, 232 &psmouse_attr_mindrag.dattr.attr, 233 &psmouse_attr_thresh.dattr.attr, 234 &psmouse_attr_upthresh.dattr.attr, 235 &psmouse_attr_ztime.dattr.attr, 236 &psmouse_attr_jenks.dattr.attr, 237 &psmouse_attr_drift_time.dattr.attr, 238 &psmouse_attr_press_to_select.dattr.attr, 239 &psmouse_attr_skipback.dattr.attr, 240 &psmouse_attr_ext_dev.dattr.attr, 241 NULL 242 }; 243 244 static struct attribute_group trackpoint_attr_group = { 245 .is_visible = trackpoint_is_attr_visible, 246 .attrs = trackpoint_attrs, 247 }; 248 249 #define TRACKPOINT_UPDATE(_power_on, _psmouse, _tp, _name) \ 250 do { \ 251 struct trackpoint_attr_data *_attr = &trackpoint_attr_##_name; \ 252 \ 253 if ((!_power_on || _tp->_name != _attr->power_on_default) && \ 254 trackpoint_is_attr_available(_psmouse, \ 255 &psmouse_attr_##_name.dattr.attr)) { \ 256 if (!_attr->mask) \ 257 trackpoint_write(&_psmouse->ps2dev, \ 258 _attr->command, _tp->_name); \ 259 else \ 260 trackpoint_update_bit(&_psmouse->ps2dev, \ 261 _attr->command, _attr->mask, \ 262 _tp->_name); \ 263 } \ 264 } while (0) 265 266 #define TRACKPOINT_SET_POWER_ON_DEFAULT(_tp, _name) \ 267 do { \ 268 _tp->_name = trackpoint_attr_##_name.power_on_default; \ 269 } while (0) 270 271 static int trackpoint_start_protocol(struct psmouse *psmouse, 272 u8 *variant_id, u8 *firmware_id) 273 { 274 u8 param[2] = { 0 }; 275 int error; 276 277 error = ps2_command(&psmouse->ps2dev, 278 param, MAKE_PS2_CMD(0, 2, TP_READ_ID)); 279 if (error) 280 return error; 281 282 switch (param[0]) { 283 case TP_VARIANT_IBM: 284 case TP_VARIANT_ALPS: 285 case TP_VARIANT_ELAN: 286 case TP_VARIANT_NXP: 287 case TP_VARIANT_JYT_SYNAPTICS: 288 case TP_VARIANT_SYNAPTICS: 289 if (variant_id) 290 *variant_id = param[0]; 291 if (firmware_id) 292 *firmware_id = param[1]; 293 return 0; 294 } 295 296 return -ENODEV; 297 } 298 299 /* 300 * Write parameters to trackpad. 301 * in_power_on_state: Set to true if TP is in default / power-on state (ex. if 302 * power-on reset was run). If so, values will only be 303 * written to TP if they differ from power-on default. 304 */ 305 static int trackpoint_sync(struct psmouse *psmouse, bool in_power_on_state) 306 { 307 struct trackpoint_data *tp = psmouse->private; 308 309 if (!in_power_on_state && tp->variant_id == TP_VARIANT_IBM) { 310 /* 311 * Disable features that may make device unusable 312 * with this driver. 313 */ 314 trackpoint_update_bit(&psmouse->ps2dev, TP_TOGGLE_TWOHAND, 315 TP_MASK_TWOHAND, TP_DEF_TWOHAND); 316 317 trackpoint_update_bit(&psmouse->ps2dev, TP_TOGGLE_SOURCE_TAG, 318 TP_MASK_SOURCE_TAG, TP_DEF_SOURCE_TAG); 319 320 trackpoint_update_bit(&psmouse->ps2dev, TP_TOGGLE_MB, 321 TP_MASK_MB, TP_DEF_MB); 322 } 323 324 /* 325 * These properties can be changed in this driver. Only 326 * configure them if the values are non-default or if the TP is in 327 * an unknown state. 328 */ 329 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, sensitivity); 330 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, inertia); 331 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, speed); 332 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, reach); 333 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, draghys); 334 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, mindrag); 335 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, thresh); 336 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, upthresh); 337 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, ztime); 338 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, jenks); 339 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, drift_time); 340 341 /* toggles */ 342 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, press_to_select); 343 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, skipback); 344 TRACKPOINT_UPDATE(in_power_on_state, psmouse, tp, ext_dev); 345 346 return 0; 347 } 348 349 static void trackpoint_defaults(struct trackpoint_data *tp) 350 { 351 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, sensitivity); 352 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, speed); 353 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, reach); 354 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, draghys); 355 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, mindrag); 356 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, thresh); 357 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, upthresh); 358 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, ztime); 359 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, jenks); 360 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, drift_time); 361 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, inertia); 362 363 /* toggles */ 364 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, press_to_select); 365 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, skipback); 366 TRACKPOINT_SET_POWER_ON_DEFAULT(tp, ext_dev); 367 } 368 369 static void trackpoint_disconnect(struct psmouse *psmouse) 370 { 371 device_remove_group(&psmouse->ps2dev.serio->dev, 372 &trackpoint_attr_group); 373 374 kfree(psmouse->private); 375 psmouse->private = NULL; 376 } 377 378 static int trackpoint_reconnect(struct psmouse *psmouse) 379 { 380 struct trackpoint_data *tp = psmouse->private; 381 int error; 382 bool was_reset; 383 384 error = trackpoint_start_protocol(psmouse, NULL, NULL); 385 if (error) 386 return error; 387 388 was_reset = tp->variant_id == TP_VARIANT_IBM && 389 trackpoint_power_on_reset(&psmouse->ps2dev) == 0; 390 391 error = trackpoint_sync(psmouse, was_reset); 392 if (error) 393 return error; 394 395 return 0; 396 } 397 398 /* List of known incapable device PNP IDs */ 399 static const char * const dt_incompatible_devices[] = { 400 "LEN0304", 401 "LEN0306", 402 "LEN0317", 403 "LEN031A", 404 "LEN031B", 405 "LEN031C", 406 "LEN031D", 407 }; 408 409 /* 410 * Checks if it's a doubletap capable device. 411 * The PNP ID format is "PNP: LEN030d PNP0f13". 412 */ 413 static bool trackpoint_is_dt_capable(const char *pnp_id) 414 { 415 size_t i; 416 417 if (!pnp_id) 418 return false; 419 420 /* Must start with "PNP: LEN03" */ 421 if (!strstarts(pnp_id, "PNP: LEN03")) 422 return false; 423 424 /* Ensure enough length before comparing */ 425 if (strlen(pnp_id) < 12) 426 return false; 427 428 /* Check deny-list */ 429 for (i = 0; i < ARRAY_SIZE(dt_incompatible_devices); i++) { 430 if (!strncmp(pnp_id + 5, dt_incompatible_devices[i], 7)) 431 return false; 432 } 433 return true; 434 } 435 436 int trackpoint_detect(struct psmouse *psmouse, bool set_properties) 437 { 438 struct ps2dev *ps2dev = &psmouse->ps2dev; 439 struct trackpoint_data *tp; 440 u8 variant_id; 441 u8 firmware_id; 442 u8 button_info; 443 int error; 444 445 error = trackpoint_start_protocol(psmouse, &variant_id, &firmware_id); 446 if (error) 447 return error; 448 449 if (!set_properties) 450 return 0; 451 452 tp = kzalloc_obj(*tp); 453 if (!tp) 454 return -ENOMEM; 455 456 trackpoint_defaults(tp); 457 tp->variant_id = variant_id; 458 tp->firmware_id = firmware_id; 459 460 psmouse->private = tp; 461 462 psmouse->vendor = trackpoint_variants[variant_id]; 463 psmouse->name = "TrackPoint"; 464 465 psmouse->reconnect = trackpoint_reconnect; 466 psmouse->disconnect = trackpoint_disconnect; 467 468 if (variant_id != TP_VARIANT_IBM) { 469 /* Newer variants do not support extended button query. */ 470 button_info = 0x33; 471 } else { 472 error = trackpoint_read(ps2dev, TP_EXT_BTN, &button_info); 473 if (error) { 474 psmouse_warn(psmouse, 475 "failed to get extended button data, assuming 3 buttons\n"); 476 button_info = 0x33; 477 } else if (!button_info) { 478 psmouse_warn(psmouse, 479 "got 0 in extended button data, assuming 3 buttons\n"); 480 button_info = 0x33; 481 } 482 } 483 484 if ((button_info & 0x0f) >= 3) 485 input_set_capability(psmouse->dev, EV_KEY, BTN_MIDDLE); 486 487 __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); 488 __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); 489 490 if (variant_id != TP_VARIANT_IBM || 491 trackpoint_power_on_reset(ps2dev) != 0) { 492 /* 493 * Write defaults to TP if we did not reset the trackpoint. 494 */ 495 trackpoint_sync(psmouse, false); 496 } 497 498 error = device_add_group(&ps2dev->serio->dev, &trackpoint_attr_group); 499 if (error) { 500 psmouse_err(psmouse, 501 "failed to create sysfs attributes, error: %d\n", 502 error); 503 kfree(psmouse->private); 504 psmouse->private = NULL; 505 return -1; 506 } 507 508 psmouse_info(psmouse, 509 "%s TrackPoint firmware: 0x%02x, buttons: %d/%d\n", 510 psmouse->vendor, firmware_id, 511 (button_info & 0xf0) >> 4, button_info & 0x0f); 512 513 if (trackpoint_is_dt_capable(ps2dev->serio->firmware_id)) { 514 error = trackpoint_write(ps2dev, TP_DOUBLETAP, TP_DOUBLETAP_ENABLE); 515 if (error) 516 psmouse_warn(psmouse, "Failed to enable doubletap: %d\n", error); 517 } 518 519 return 0; 520 } 521 522