diff options
| -rw-r--r-- | drivers/input/mouse/trackpoint.c | 248 | ||||
| -rw-r--r-- | drivers/input/mouse/trackpoint.h | 34 |
2 files changed, 172 insertions, 110 deletions
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index 92a8898682a6..bbd29220dbe9 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
| @@ -19,6 +19,13 @@ | |||
| 19 | #include "psmouse.h" | 19 | #include "psmouse.h" |
| 20 | #include "trackpoint.h" | 20 | #include "trackpoint.h" |
| 21 | 21 | ||
| 22 | static const char * const trackpoint_variants[] = { | ||
| 23 | [TP_VARIANT_IBM] = "IBM", | ||
| 24 | [TP_VARIANT_ALPS] = "ALPS", | ||
| 25 | [TP_VARIANT_ELAN] = "Elan", | ||
| 26 | [TP_VARIANT_NXP] = "NXP", | ||
| 27 | }; | ||
| 28 | |||
| 22 | /* | 29 | /* |
| 23 | * Power-on Reset: Resets all trackpoint parameters, including RAM values, | 30 | * Power-on Reset: Resets all trackpoint parameters, including RAM values, |
| 24 | * to defaults. | 31 | * to defaults. |
| @@ -26,7 +33,7 @@ | |||
| 26 | */ | 33 | */ |
| 27 | static int trackpoint_power_on_reset(struct ps2dev *ps2dev) | 34 | static int trackpoint_power_on_reset(struct ps2dev *ps2dev) |
| 28 | { | 35 | { |
| 29 | unsigned char results[2]; | 36 | u8 results[2]; |
| 30 | int tries = 0; | 37 | int tries = 0; |
| 31 | 38 | ||
| 32 | /* Issue POR command, and repeat up to once if 0xFC00 received */ | 39 | /* Issue POR command, and repeat up to once if 0xFC00 received */ |
| @@ -38,7 +45,7 @@ static int trackpoint_power_on_reset(struct ps2dev *ps2dev) | |||
| 38 | 45 | ||
| 39 | /* Check for success response -- 0xAA00 */ | 46 | /* Check for success response -- 0xAA00 */ |
| 40 | if (results[0] != 0xAA || results[1] != 0x00) | 47 | if (results[0] != 0xAA || results[1] != 0x00) |
| 41 | return -1; | 48 | return -ENODEV; |
| 42 | 49 | ||
| 43 | return 0; | 50 | return 0; |
| 44 | } | 51 | } |
| @@ -46,8 +53,7 @@ static int trackpoint_power_on_reset(struct ps2dev *ps2dev) | |||
| 46 | /* | 53 | /* |
| 47 | * Device IO: read, write and toggle bit | 54 | * Device IO: read, write and toggle bit |
| 48 | */ | 55 | */ |
| 49 | static int trackpoint_read(struct ps2dev *ps2dev, | 56 | static int trackpoint_read(struct ps2dev *ps2dev, u8 loc, u8 *results) |
| 50 | unsigned char loc, unsigned char *results) | ||
| 51 | { | 57 | { |
| 52 | if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || | 58 | if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || |
| 53 | ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) { | 59 | ps2_command(ps2dev, results, MAKE_PS2_CMD(0, 1, loc))) { |
| @@ -57,8 +63,7 @@ static int trackpoint_read(struct ps2dev *ps2dev, | |||
| 57 | return 0; | 63 | return 0; |
| 58 | } | 64 | } |
| 59 | 65 | ||
| 60 | static int trackpoint_write(struct ps2dev *ps2dev, | 66 | static int trackpoint_write(struct ps2dev *ps2dev, u8 loc, u8 val) |
| 61 | unsigned char loc, unsigned char val) | ||
| 62 | { | 67 | { |
| 63 | if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || | 68 | if (ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_COMMAND)) || |
| 64 | ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) || | 69 | ps2_command(ps2dev, NULL, MAKE_PS2_CMD(0, 0, TP_WRITE_MEM)) || |
| @@ -70,8 +75,7 @@ static int trackpoint_write(struct ps2dev *ps2dev, | |||
| 70 | return 0; | 75 | return 0; |
| 71 | } | 76 | } |
| 72 | 77 | ||
| 73 | static int trackpoint_toggle_bit(struct ps2dev *ps2dev, | 78 | static int trackpoint_toggle_bit(struct ps2dev *ps2dev, u8 loc, u8 mask) |
| 74 | unsigned char loc, unsigned char mask) | ||
| 75 | { | 79 | { |
| 76 | /* Bad things will happen if the loc param isn't in this range */ | 80 | /* Bad things will happen if the loc param isn't in this range */ |
| 77 | if (loc < 0x20 || loc >= 0x2F) | 81 | if (loc < 0x20 || loc >= 0x2F) |
| @@ -87,11 +91,11 @@ static int trackpoint_toggle_bit(struct ps2dev *ps2dev, | |||
| 87 | return 0; | 91 | return 0; |
| 88 | } | 92 | } |
| 89 | 93 | ||
| 90 | static int trackpoint_update_bit(struct ps2dev *ps2dev, unsigned char loc, | 94 | static int trackpoint_update_bit(struct ps2dev *ps2dev, |
| 91 | unsigned char mask, unsigned char value) | 95 | u8 loc, u8 mask, u8 value) |
| 92 | { | 96 | { |
| 93 | int retval = 0; | 97 | int retval = 0; |
| 94 | unsigned char data; | 98 | u8 data; |
| 95 | 99 | ||
| 96 | trackpoint_read(ps2dev, loc, &data); | 100 | trackpoint_read(ps2dev, loc, &data); |
| 97 | if (((data & mask) == mask) != !!value) | 101 | if (((data & mask) == mask) != !!value) |
| @@ -105,17 +109,18 @@ static int trackpoint_update_bit(struct ps2dev *ps2dev, unsigned char loc, | |||
| 105 | */ | 109 | */ |
| 106 | struct trackpoint_attr_data { | 110 | struct trackpoint_attr_data { |
| 107 | size_t field_offset; | 111 | size_t field_offset; |
| 108 | unsigned char command; | 112 | u8 command; |
| 109 | unsigned char mask; | 113 | u8 mask; |
| 110 | unsigned char inverted; | 114 | bool inverted; |
| 111 | unsigned char power_on_default; | 115 | u8 power_on_default; |
| 112 | }; | 116 | }; |
| 113 | 117 | ||
| 114 | static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, void *data, char *buf) | 118 | static ssize_t trackpoint_show_int_attr(struct psmouse *psmouse, |
| 119 | void *data, char *buf) | ||
| 115 | { | 120 | { |
| 116 | struct trackpoint_data *tp = psmouse->private; | 121 | struct trackpoint_data *tp = psmouse->private; |
| 117 | struct trackpoint_attr_data *attr = data; | 122 | struct trackpoint_attr_data *attr = data; |
| 118 | unsigned char value = *(unsigned char *)((char *)tp + attr->field_offset); | 123 | u8 value = *(u8 *)((void *)tp + attr->field_offset); |
| 119 | 124 | ||
| 120 | if (attr->inverted) | 125 | if (attr->inverted) |
| 121 | value = !value; | 126 | value = !value; |
| @@ -128,8 +133,8 @@ static ssize_t trackpoint_set_int_attr(struct psmouse *psmouse, void *data, | |||
| 128 | { | 133 | { |
| 129 | struct trackpoint_data *tp = psmouse->private; | 134 | struct trackpoint_data *tp = psmouse->private; |
| 130 | struct trackpoint_attr_data *attr = data; | 135 | struct trackpoint_attr_data *attr = data; |
| 131 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 136 | u8 *field = (void *)tp + attr->field_offset; |
| 132 | unsigned char value; | 137 | u8 value; |
| 133 | int err; | 138 | int err; |
| 134 | 139 | ||
| 135 | err = kstrtou8(buf, 10, &value); | 140 | err = kstrtou8(buf, 10, &value); |
| @@ -157,17 +162,14 @@ static ssize_t trackpoint_set_bit_attr(struct psmouse *psmouse, void *data, | |||
| 157 | { | 162 | { |
| 158 | struct trackpoint_data *tp = psmouse->private; | 163 | struct trackpoint_data *tp = psmouse->private; |
| 159 | struct trackpoint_attr_data *attr = data; | 164 | struct trackpoint_attr_data *attr = data; |
| 160 | unsigned char *field = (unsigned char *)((char *)tp + attr->field_offset); | 165 | bool *field = (void *)tp + attr->field_offset; |
| 161 | unsigned int value; | 166 | bool value; |
| 162 | int err; | 167 | int err; |
| 163 | 168 | ||
| 164 | err = kstrtouint(buf, 10, &value); | 169 | err = kstrtobool(buf, &value); |
| 165 | if (err) | 170 | if (err) |
| 166 | return err; | 171 | return err; |
| 167 | 172 | ||
| 168 | if (value > 1) | ||
| 169 | return -EINVAL; | ||
| 170 | |||
| 171 | if (attr->inverted) | 173 | if (attr->inverted) |
| 172 | value = !value; | 174 | value = !value; |
| 173 | 175 | ||
| @@ -193,30 +195,6 @@ PSMOUSE_DEFINE_ATTR(_name, S_IWUSR | S_IRUGO, \ | |||
| 193 | &trackpoint_attr_##_name, \ | 195 | &trackpoint_attr_##_name, \ |
| 194 | trackpoint_show_int_attr, trackpoint_set_bit_attr) | 196 | trackpoint_show_int_attr, trackpoint_set_bit_attr) |
| 195 | 197 | ||
| 196 | #define TRACKPOINT_UPDATE_BIT(_psmouse, _tp, _name) \ | ||
| 197 | do { \ | ||
| 198 | struct trackpoint_attr_data *_attr = &trackpoint_attr_##_name; \ | ||
| 199 | \ | ||
| 200 | trackpoint_update_bit(&_psmouse->ps2dev, \ | ||
| 201 | _attr->command, _attr->mask, _tp->_name); \ | ||
| 202 | } while (0) | ||
| 203 | |||
| 204 | #define TRACKPOINT_UPDATE(_power_on, _psmouse, _tp, _name) \ | ||
| 205 | do { \ | ||
| 206 | if (!_power_on || \ | ||
| 207 | _tp->_name != trackpoint_attr_##_name.power_on_default) { \ | ||
| 208 | if (!trackpoint_attr_##_name.mask) \ | ||
| 209 | trackpoint_write(&_psmouse->ps2dev, \ | ||
| 210 | trackpoint_attr_##_name.command, \ | ||
| 211 | _tp->_name); \ | ||
| 212 | else \ | ||
| 213 | TRACKPOINT_UPDATE_BIT(_psmouse, _tp, _name); \ | ||
| 214 | } \ | ||
| 215 | } while (0) | ||
| 216 | |||
| 217 | #define TRACKPOINT_SET_POWER_ON_DEFAULT(_tp, _name) \ | ||
| 218 | (_tp->_name = trackpoint_attr_##_name.power_on_default) | ||
| 219 | |||
| 220 | TRACKPOINT_INT_ATTR(sensitivity, TP_SENS, TP_DEF_SENS); | 198 | TRACKPOINT_INT_ATTR(sensitivity, TP_SENS, TP_DEF_SENS); |
| 221 | TRACKPOINT_INT_ATTR(speed, TP_SPEED, TP_DEF_SPEED); | 199 | TRACKPOINT_INT_ATTR(speed, TP_SPEED, TP_DEF_SPEED); |
| 222 | TRACKPOINT_INT_ATTR(inertia, TP_INERTIA, TP_DEF_INERTIA); | 200 | TRACKPOINT_INT_ATTR(inertia, TP_INERTIA, TP_DEF_INERTIA); |
| @@ -229,13 +207,33 @@ TRACKPOINT_INT_ATTR(ztime, TP_Z_TIME, TP_DEF_Z_TIME); | |||
| 229 | TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV, TP_DEF_JENKS_CURV); | 207 | TRACKPOINT_INT_ATTR(jenks, TP_JENKS_CURV, TP_DEF_JENKS_CURV); |
| 230 | TRACKPOINT_INT_ATTR(drift_time, TP_DRIFT_TIME, TP_DEF_DRIFT_TIME); | 208 | TRACKPOINT_INT_ATTR(drift_time, TP_DRIFT_TIME, TP_DEF_DRIFT_TIME); |
| 231 | 209 | ||
| 232 | TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, 0, | 210 | TRACKPOINT_BIT_ATTR(press_to_select, TP_TOGGLE_PTSON, TP_MASK_PTSON, false, |
| 233 | TP_DEF_PTSON); | 211 | TP_DEF_PTSON); |
| 234 | TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, 0, | 212 | TRACKPOINT_BIT_ATTR(skipback, TP_TOGGLE_SKIPBACK, TP_MASK_SKIPBACK, false, |
| 235 | TP_DEF_SKIPBACK); | 213 | TP_DEF_SKIPBACK); |
| 236 | TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, 1, | 214 | TRACKPOINT_BIT_ATTR(ext_dev, TP_TOGGLE_EXT_DEV, TP_MASK_EXT_DEV, true, |
| 237 | TP_DEF_EXT_DEV); | 215 | TP_DEF_EXT_DEV); |
| 238 | 216 | ||
| 217 | static bool trackpoint_is_attr_available(struct psmouse *psmouse, | ||
| 218 | struct attribute *attr) | ||
| 219 | { | ||
| 220 | struct trackpoint_data *tp = psmouse->private; | ||
| 221 | |||
| 222 | return tp->variant_id == TP_VARIANT_IBM || | ||
| 223 | attr == &psmouse_attr_sensitivity.dattr.attr || | ||
| 224 | attr == &psmouse_attr_press_to_select.dattr.attr; | ||
| 225 | } | ||
| 226 | |||
| 227 | static umode_t trackpoint_is_attr_visible(struct kobject *kobj, | ||
| 228 | struct attribute *attr, int n) | ||
| 229 | { | ||
| 230 | struct device *dev = container_of(kobj, struct device, kobj); | ||
| 231 | struct serio *serio = to_serio_port(dev); | ||
| 232 | struct psmouse *psmouse = serio_get_drvdata(serio); | ||
| 233 | |||
| 234 | return trackpoint_is_attr_available(psmouse, attr) ? attr->mode : 0; | ||
| 235 | } | ||
| 236 | |||
| 239 | static struct attribute *trackpoint_attrs[] = { | 237 | static struct attribute *trackpoint_attrs[] = { |
| 240 | &psmouse_attr_sensitivity.dattr.attr, | 238 | &psmouse_attr_sensitivity.dattr.attr, |
| 241 | &psmouse_attr_speed.dattr.attr, | 239 | &psmouse_attr_speed.dattr.attr, |
| @@ -255,24 +253,56 @@ static struct attribute *trackpoint_attrs[] = { | |||
| 255 | }; | 253 | }; |
| 256 | 254 | ||
| 257 | static struct attribute_group trackpoint_attr_group = { | 255 | static struct attribute_group trackpoint_attr_group = { |
| 258 | .attrs = trackpoint_attrs, | 256 | .is_visible = trackpoint_is_attr_visible, |
| 257 | .attrs = trackpoint_attrs, | ||
| 259 | }; | 258 | }; |
| 260 | 259 | ||
| 261 | static int trackpoint_start_protocol(struct psmouse *psmouse, unsigned char *firmware_id) | 260 | #define TRACKPOINT_UPDATE(_power_on, _psmouse, _tp, _name) \ |
| 262 | { | 261 | do { \ |
| 263 | unsigned char param[2] = { 0 }; | 262 | struct trackpoint_attr_data *_attr = &trackpoint_attr_##_name; \ |
| 263 | \ | ||
| 264 | if ((!_power_on || _tp->_name != _attr->power_on_default) && \ | ||
| 265 | trackpoint_is_attr_available(_psmouse, \ | ||
| 266 | &psmouse_attr_##_name.dattr.attr)) { \ | ||
| 267 | if (!_attr->mask) \ | ||
| 268 | trackpoint_write(&_psmouse->ps2dev, \ | ||
| 269 | _attr->command, _tp->_name); \ | ||
| 270 | else \ | ||
| 271 | trackpoint_update_bit(&_psmouse->ps2dev, \ | ||
| 272 | _attr->command, _attr->mask, \ | ||
| 273 | _tp->_name); \ | ||
| 274 | } \ | ||
| 275 | } while (0) | ||
| 264 | 276 | ||
| 265 | if (ps2_command(&psmouse->ps2dev, param, MAKE_PS2_CMD(0, 2, TP_READ_ID))) | 277 | #define TRACKPOINT_SET_POWER_ON_DEFAULT(_tp, _name) \ |
| 266 | return -1; | 278 | do { \ |
| 279 | _tp->_name = trackpoint_attr_##_name.power_on_default; \ | ||
| 280 | } while (0) | ||
| 267 | 281 | ||
| 268 | /* add new TP ID. */ | 282 | static int trackpoint_start_protocol(struct psmouse *psmouse, |
| 269 | if (!(param[0] & TP_MAGIC_IDENT)) | 283 | u8 *variant_id, u8 *firmware_id) |
| 270 | return -1; | 284 | { |
| 285 | u8 param[2] = { 0 }; | ||
| 286 | int error; | ||
| 271 | 287 | ||
| 272 | if (firmware_id) | 288 | error = ps2_command(&psmouse->ps2dev, |
| 273 | *firmware_id = param[1]; | 289 | param, MAKE_PS2_CMD(0, 2, TP_READ_ID)); |
| 290 | if (error) | ||
| 291 | return error; | ||
| 292 | |||
| 293 | switch (param[0]) { | ||
| 294 | case TP_VARIANT_IBM: | ||
| 295 | case TP_VARIANT_ALPS: | ||
| 296 | case TP_VARIANT_ELAN: | ||
| 297 | case TP_VARIANT_NXP: | ||
| 298 | if (variant_id) | ||
| 299 | *variant_id = param[0]; | ||
| 300 | if (firmware_id) | ||
| 301 | *firmware_id = param[1]; | ||
| 302 | return 0; | ||
| 303 | } | ||
| 274 | 304 | ||
| 275 | return 0; | 305 | return -ENODEV; |
| 276 | } | 306 | } |
| 277 | 307 | ||
| 278 | /* | 308 | /* |
| @@ -285,7 +315,7 @@ static int trackpoint_sync(struct psmouse *psmouse, bool in_power_on_state) | |||
| 285 | { | 315 | { |
| 286 | struct trackpoint_data *tp = psmouse->private; | 316 | struct trackpoint_data *tp = psmouse->private; |
| 287 | 317 | ||
| 288 | if (!in_power_on_state) { | 318 | if (!in_power_on_state && tp->variant_id == TP_VARIANT_IBM) { |
| 289 | /* | 319 | /* |
| 290 | * Disable features that may make device unusable | 320 | * Disable features that may make device unusable |
| 291 | * with this driver. | 321 | * with this driver. |
| @@ -347,7 +377,8 @@ static void trackpoint_defaults(struct trackpoint_data *tp) | |||
| 347 | 377 | ||
| 348 | static void trackpoint_disconnect(struct psmouse *psmouse) | 378 | static void trackpoint_disconnect(struct psmouse *psmouse) |
| 349 | { | 379 | { |
| 350 | sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj, &trackpoint_attr_group); | 380 | device_remove_group(&psmouse->ps2dev.serio->dev, |
| 381 | &trackpoint_attr_group); | ||
| 351 | 382 | ||
| 352 | kfree(psmouse->private); | 383 | kfree(psmouse->private); |
| 353 | psmouse->private = NULL; | 384 | psmouse->private = NULL; |
| @@ -355,14 +386,20 @@ static void trackpoint_disconnect(struct psmouse *psmouse) | |||
| 355 | 386 | ||
| 356 | static int trackpoint_reconnect(struct psmouse *psmouse) | 387 | static int trackpoint_reconnect(struct psmouse *psmouse) |
| 357 | { | 388 | { |
| 358 | int reset_fail; | 389 | struct trackpoint_data *tp = psmouse->private; |
| 390 | int error; | ||
| 391 | bool was_reset; | ||
| 359 | 392 | ||
| 360 | if (trackpoint_start_protocol(psmouse, NULL)) | 393 | error = trackpoint_start_protocol(psmouse, NULL, NULL); |
| 361 | return -1; | 394 | if (error) |
| 395 | return error; | ||
| 362 | 396 | ||
| 363 | reset_fail = trackpoint_power_on_reset(&psmouse->ps2dev); | 397 | was_reset = tp->variant_id == TP_VARIANT_IBM && |
| 364 | if (trackpoint_sync(psmouse, !reset_fail)) | 398 | trackpoint_power_on_reset(&psmouse->ps2dev) == 0; |
| 365 | return -1; | 399 | |
| 400 | error = trackpoint_sync(psmouse, was_reset); | ||
| 401 | if (error) | ||
| 402 | return error; | ||
| 366 | 403 | ||
| 367 | return 0; | 404 | return 0; |
| 368 | } | 405 | } |
| @@ -370,49 +407,66 @@ static int trackpoint_reconnect(struct psmouse *psmouse) | |||
| 370 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | 407 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
| 371 | { | 408 | { |
| 372 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 409 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 373 | unsigned char firmware_id; | 410 | struct trackpoint_data *tp; |
| 374 | unsigned char button_info; | 411 | u8 variant_id; |
| 412 | u8 firmware_id; | ||
| 413 | u8 button_info; | ||
| 375 | int error; | 414 | int error; |
| 376 | 415 | ||
| 377 | if (trackpoint_start_protocol(psmouse, &firmware_id)) | 416 | error = trackpoint_start_protocol(psmouse, &variant_id, &firmware_id); |
| 378 | return -1; | 417 | if (error) |
| 418 | return error; | ||
| 379 | 419 | ||
| 380 | if (!set_properties) | 420 | if (!set_properties) |
| 381 | return 0; | 421 | return 0; |
| 382 | 422 | ||
| 383 | if (trackpoint_read(ps2dev, TP_EXT_BTN, &button_info)) { | 423 | tp = kzalloc(sizeof(*tp), GFP_KERNEL); |
| 384 | psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n"); | 424 | if (!tp) |
| 385 | button_info = 0x33; | ||
| 386 | } else if (!button_info) { | ||
| 387 | psmouse_warn(psmouse, "got 0 in extended button data, assuming 3 buttons\n"); | ||
| 388 | button_info = 0x33; | ||
| 389 | } | ||
| 390 | |||
| 391 | psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); | ||
| 392 | if (!psmouse->private) | ||
| 393 | return -ENOMEM; | 425 | return -ENOMEM; |
| 394 | 426 | ||
| 395 | psmouse->vendor = "IBM"; | 427 | trackpoint_defaults(tp); |
| 428 | tp->variant_id = variant_id; | ||
| 429 | tp->firmware_id = firmware_id; | ||
| 430 | |||
| 431 | psmouse->private = tp; | ||
| 432 | |||
| 433 | psmouse->vendor = trackpoint_variants[variant_id]; | ||
| 396 | psmouse->name = "TrackPoint"; | 434 | psmouse->name = "TrackPoint"; |
| 397 | 435 | ||
| 398 | psmouse->reconnect = trackpoint_reconnect; | 436 | psmouse->reconnect = trackpoint_reconnect; |
| 399 | psmouse->disconnect = trackpoint_disconnect; | 437 | psmouse->disconnect = trackpoint_disconnect; |
| 400 | 438 | ||
| 439 | if (variant_id != TP_VARIANT_IBM) { | ||
| 440 | /* Newer variants do not support extended button query. */ | ||
| 441 | button_info = 0x33; | ||
| 442 | } else { | ||
| 443 | error = trackpoint_read(ps2dev, TP_EXT_BTN, &button_info); | ||
| 444 | if (error) { | ||
| 445 | psmouse_warn(psmouse, | ||
| 446 | "failed to get extended button data, assuming 3 buttons\n"); | ||
| 447 | button_info = 0x33; | ||
| 448 | } else if (!button_info) { | ||
| 449 | psmouse_warn(psmouse, | ||
| 450 | "got 0 in extended button data, assuming 3 buttons\n"); | ||
| 451 | button_info = 0x33; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | |||
| 401 | if ((button_info & 0x0f) >= 3) | 455 | if ((button_info & 0x0f) >= 3) |
| 402 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 456 | input_set_capability(psmouse->dev, EV_KEY, BTN_MIDDLE); |
| 403 | 457 | ||
| 404 | __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); | 458 | __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit); |
| 405 | __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); | 459 | __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit); |
| 406 | 460 | ||
| 407 | trackpoint_defaults(psmouse->private); | 461 | if (variant_id != TP_VARIANT_IBM || |
| 408 | 462 | trackpoint_power_on_reset(ps2dev) != 0) { | |
| 409 | error = trackpoint_power_on_reset(ps2dev); | 463 | /* |
| 410 | 464 | * Write defaults to TP if we did not reset the trackpoint. | |
| 411 | /* Write defaults to TP only if reset fails. */ | 465 | */ |
| 412 | if (error) | ||
| 413 | trackpoint_sync(psmouse, false); | 466 | trackpoint_sync(psmouse, false); |
| 467 | } | ||
| 414 | 468 | ||
| 415 | error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); | 469 | error = device_add_group(&ps2dev->serio->dev, &trackpoint_attr_group); |
| 416 | if (error) { | 470 | if (error) { |
| 417 | psmouse_err(psmouse, | 471 | psmouse_err(psmouse, |
| 418 | "failed to create sysfs attributes, error: %d\n", | 472 | "failed to create sysfs attributes, error: %d\n", |
| @@ -423,8 +477,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
| 423 | } | 477 | } |
| 424 | 478 | ||
| 425 | psmouse_info(psmouse, | 479 | psmouse_info(psmouse, |
| 426 | "IBM TrackPoint firmware: 0x%02x, buttons: %d/%d\n", | 480 | "%s TrackPoint firmware: 0x%02x, buttons: %d/%d\n", |
| 427 | firmware_id, | 481 | psmouse->vendor, firmware_id, |
| 428 | (button_info & 0xf0) >> 4, button_info & 0x0f); | 482 | (button_info & 0xf0) >> 4, button_info & 0x0f); |
| 429 | 483 | ||
| 430 | return 0; | 484 | return 0; |
diff --git a/drivers/input/mouse/trackpoint.h b/drivers/input/mouse/trackpoint.h index 88055755f82e..10a039148234 100644 --- a/drivers/input/mouse/trackpoint.h +++ b/drivers/input/mouse/trackpoint.h | |||
| @@ -21,10 +21,16 @@ | |||
| 21 | #define TP_COMMAND 0xE2 /* Commands start with this */ | 21 | #define TP_COMMAND 0xE2 /* Commands start with this */ |
| 22 | 22 | ||
| 23 | #define TP_READ_ID 0xE1 /* Sent for device identification */ | 23 | #define TP_READ_ID 0xE1 /* Sent for device identification */ |
| 24 | #define TP_MAGIC_IDENT 0x03 /* Sent after a TP_READ_ID followed */ | ||
| 25 | /* by the firmware ID */ | ||
| 26 | /* Firmware ID includes 0x1, 0x2, 0x3 */ | ||
| 27 | 24 | ||
| 25 | /* | ||
| 26 | * Valid first byte responses to the "Read Secondary ID" (0xE1) command. | ||
| 27 | * 0x01 was the original IBM trackpoint, others implement very limited | ||
| 28 | * subset of trackpoint features. | ||
| 29 | */ | ||
| 30 | #define TP_VARIANT_IBM 0x01 | ||
| 31 | #define TP_VARIANT_ALPS 0x02 | ||
| 32 | #define TP_VARIANT_ELAN 0x03 | ||
| 33 | #define TP_VARIANT_NXP 0x04 | ||
| 28 | 34 | ||
| 29 | /* | 35 | /* |
| 30 | * Commands | 36 | * Commands |
| @@ -136,18 +142,20 @@ | |||
| 136 | 142 | ||
| 137 | #define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd)) | 143 | #define MAKE_PS2_CMD(params, results, cmd) ((params<<12) | (results<<8) | (cmd)) |
| 138 | 144 | ||
| 139 | struct trackpoint_data | 145 | struct trackpoint_data { |
| 140 | { | 146 | u8 variant_id; |
| 141 | unsigned char sensitivity, speed, inertia, reach; | 147 | u8 firmware_id; |
| 142 | unsigned char draghys, mindrag; | 148 | |
| 143 | unsigned char thresh, upthresh; | 149 | u8 sensitivity, speed, inertia, reach; |
| 144 | unsigned char ztime, jenks; | 150 | u8 draghys, mindrag; |
| 145 | unsigned char drift_time; | 151 | u8 thresh, upthresh; |
| 152 | u8 ztime, jenks; | ||
| 153 | u8 drift_time; | ||
| 146 | 154 | ||
| 147 | /* toggles */ | 155 | /* toggles */ |
| 148 | unsigned char press_to_select; | 156 | bool press_to_select; |
| 149 | unsigned char skipback; | 157 | bool skipback; |
| 150 | unsigned char ext_dev; | 158 | bool ext_dev; |
| 151 | }; | 159 | }; |
| 152 | 160 | ||
| 153 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT | 161 | #ifdef CONFIG_MOUSE_PS2_TRACKPOINT |
