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

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input

Pull input updates from Dmitry Torokhov:
"An update to Synaptics driver that makes it usable with the 2015
lineup from Lenovo"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input:
Revert "Input: synaptics - use dmax in input_mt_assign_slots"
Input: synaptics - remove X250 from the topbuttonpad list
Input: synaptics - remove X1 Carbon 3rd gen from the topbuttonpad list
Input: synaptics - re-route tracksticks buttons on the Lenovo 2015 series
Input: synaptics - remove TOPBUTTONPAD property for Lenovos 2015
Input: synaptics - retrieve the extended capabilities in query $10
Input: synaptics - do not retrieve the board id on old firmwares
Input: synaptics - handle spurious release of trackstick buttons
Input: synaptics - fix middle button on Lenovo 2015 products
Input: synaptics - skip quirks when post-2013 dimensions
Input: synaptics - support min/max board id in min_max_pnpid_table
Input: synaptics - remove obsolete min/max quirk for X240
Input: synaptics - query min dimensions for fw v8.1
Input: synaptics - log queried and quirked dimension values
Input: synaptics - split synaptics_resolution(), query first

+185 -55
+157 -55
drivers/input/mouse/synaptics.c
··· 67 67 #define X_MAX_POSITIVE 8176 68 68 #define Y_MAX_POSITIVE 8176 69 69 70 - /* maximum ABS_MT_POSITION displacement (in mm) */ 71 - #define DMAX 10 72 - 73 70 /***************************************************************************** 74 71 * Stuff we need even when we do not want native Synaptics support 75 72 ****************************************************************************/ ··· 120 123 121 124 static bool cr48_profile_sensor; 122 125 126 + #define ANY_BOARD_ID 0 123 127 struct min_max_quirk { 124 128 const char * const *pnp_ids; 129 + struct { 130 + unsigned long int min, max; 131 + } board_id; 125 132 int x_min, x_max, y_min, y_max; 126 133 }; 127 134 128 135 static const struct min_max_quirk min_max_pnpid_table[] = { 129 136 { 130 137 (const char * const []){"LEN0033", NULL}, 138 + {ANY_BOARD_ID, ANY_BOARD_ID}, 131 139 1024, 5052, 2258, 4832 132 140 }, 133 141 { 134 - (const char * const []){"LEN0035", "LEN0042", NULL}, 142 + (const char * const []){"LEN0042", NULL}, 143 + {ANY_BOARD_ID, ANY_BOARD_ID}, 135 144 1232, 5710, 1156, 4696 136 145 }, 137 146 { 138 147 (const char * const []){"LEN0034", "LEN0036", "LEN0037", 139 148 "LEN0039", "LEN2002", "LEN2004", 140 149 NULL}, 150 + {ANY_BOARD_ID, 2961}, 141 151 1024, 5112, 2024, 4832 142 152 }, 143 153 { 144 154 (const char * const []){"LEN2001", NULL}, 155 + {ANY_BOARD_ID, ANY_BOARD_ID}, 145 156 1024, 5022, 2508, 4832 146 157 }, 147 158 { 148 159 (const char * const []){"LEN2006", NULL}, 160 + {ANY_BOARD_ID, ANY_BOARD_ID}, 149 161 1264, 5675, 1171, 4688 150 162 }, 151 163 { } ··· 181 175 "LEN0041", 182 176 "LEN0042", /* Yoga */ 183 177 "LEN0045", 184 - "LEN0046", 185 178 "LEN0047", 186 - "LEN0048", 187 179 "LEN0049", 188 180 "LEN2000", 189 181 "LEN2001", /* Edge E431 */ ··· 239 235 return 0; 240 236 } 241 237 238 + static int synaptics_more_extended_queries(struct psmouse *psmouse) 239 + { 240 + struct synaptics_data *priv = psmouse->private; 241 + unsigned char buf[3]; 242 + 243 + if (synaptics_send_cmd(psmouse, SYN_QUE_MEXT_CAPAB_10, buf)) 244 + return -1; 245 + 246 + priv->ext_cap_10 = (buf[0]<<16) | (buf[1]<<8) | buf[2]; 247 + 248 + return 0; 249 + } 250 + 242 251 /* 243 - * Read the board id from the touchpad 252 + * Read the board id and the "More Extended Queries" from the touchpad 244 253 * The board id is encoded in the "QUERY MODES" response 245 254 */ 246 - static int synaptics_board_id(struct psmouse *psmouse) 255 + static int synaptics_query_modes(struct psmouse *psmouse) 247 256 { 248 257 struct synaptics_data *priv = psmouse->private; 249 258 unsigned char bid[3]; 250 259 260 + /* firmwares prior 7.5 have no board_id encoded */ 261 + if (SYN_ID_FULL(priv->identity) < 0x705) 262 + return 0; 263 + 251 264 if (synaptics_send_cmd(psmouse, SYN_QUE_MODES, bid)) 252 265 return -1; 253 266 priv->board_id = ((bid[0] & 0xfc) << 6) | bid[1]; 267 + 268 + if (SYN_MEXT_CAP_BIT(bid[0])) 269 + return synaptics_more_extended_queries(psmouse); 270 + 254 271 return 0; 255 272 } 256 273 ··· 371 346 { 372 347 struct synaptics_data *priv = psmouse->private; 373 348 unsigned char resp[3]; 374 - int i; 375 349 376 350 if (SYN_ID_MAJOR(priv->identity) < 4) 377 351 return 0; ··· 382 358 } 383 359 } 384 360 385 - for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { 386 - if (psmouse_matches_pnp_id(psmouse, 387 - min_max_pnpid_table[i].pnp_ids)) { 388 - priv->x_min = min_max_pnpid_table[i].x_min; 389 - priv->x_max = min_max_pnpid_table[i].x_max; 390 - priv->y_min = min_max_pnpid_table[i].y_min; 391 - priv->y_max = min_max_pnpid_table[i].y_max; 392 - return 0; 393 - } 394 - } 395 - 396 361 if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 5 && 397 362 SYN_CAP_MAX_DIMENSIONS(priv->ext_cap_0c)) { 398 363 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MAX_COORDS, resp)) { ··· 390 377 } else { 391 378 priv->x_max = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); 392 379 priv->y_max = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); 380 + psmouse_info(psmouse, 381 + "queried max coordinates: x [..%d], y [..%d]\n", 382 + priv->x_max, priv->y_max); 393 383 } 394 384 } 395 385 396 - if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 && 397 - SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c)) { 386 + if (SYN_CAP_MIN_DIMENSIONS(priv->ext_cap_0c) && 387 + (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 7 || 388 + /* 389 + * Firmware v8.1 does not report proper number of extended 390 + * capabilities, but has been proven to report correct min 391 + * coordinates. 392 + */ 393 + SYN_ID_FULL(priv->identity) == 0x801)) { 398 394 if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_MIN_COORDS, resp)) { 399 395 psmouse_warn(psmouse, 400 396 "device claims to have min coordinates query, but I'm not able to read it.\n"); 401 397 } else { 402 398 priv->x_min = (resp[0] << 5) | ((resp[1] & 0x0f) << 1); 403 399 priv->y_min = (resp[2] << 5) | ((resp[1] & 0xf0) >> 3); 400 + psmouse_info(psmouse, 401 + "queried min coordinates: x [%d..], y [%d..]\n", 402 + priv->x_min, priv->y_min); 404 403 } 405 404 } 406 405 407 406 return 0; 407 + } 408 + 409 + /* 410 + * Apply quirk(s) if the hardware matches 411 + */ 412 + 413 + static void synaptics_apply_quirks(struct psmouse *psmouse) 414 + { 415 + struct synaptics_data *priv = psmouse->private; 416 + int i; 417 + 418 + for (i = 0; min_max_pnpid_table[i].pnp_ids; i++) { 419 + if (!psmouse_matches_pnp_id(psmouse, 420 + min_max_pnpid_table[i].pnp_ids)) 421 + continue; 422 + 423 + if (min_max_pnpid_table[i].board_id.min != ANY_BOARD_ID && 424 + priv->board_id < min_max_pnpid_table[i].board_id.min) 425 + continue; 426 + 427 + if (min_max_pnpid_table[i].board_id.max != ANY_BOARD_ID && 428 + priv->board_id > min_max_pnpid_table[i].board_id.max) 429 + continue; 430 + 431 + priv->x_min = min_max_pnpid_table[i].x_min; 432 + priv->x_max = min_max_pnpid_table[i].x_max; 433 + priv->y_min = min_max_pnpid_table[i].y_min; 434 + priv->y_max = min_max_pnpid_table[i].y_max; 435 + psmouse_info(psmouse, 436 + "quirked min/max coordinates: x [%d..%d], y [%d..%d]\n", 437 + priv->x_min, priv->x_max, 438 + priv->y_min, priv->y_max); 439 + break; 440 + } 408 441 } 409 442 410 443 static int synaptics_query_hardware(struct psmouse *psmouse) ··· 461 402 return -1; 462 403 if (synaptics_firmware_id(psmouse)) 463 404 return -1; 464 - if (synaptics_board_id(psmouse)) 405 + if (synaptics_query_modes(psmouse)) 465 406 return -1; 466 407 if (synaptics_capability(psmouse)) 467 408 return -1; 468 409 if (synaptics_resolution(psmouse)) 469 410 return -1; 411 + 412 + synaptics_apply_quirks(psmouse); 470 413 471 414 return 0; 472 415 } ··· 577 516 return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4; 578 517 } 579 518 580 - static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet) 519 + static void synaptics_pass_pt_packet(struct psmouse *psmouse, 520 + struct serio *ptport, 521 + unsigned char *packet) 581 522 { 523 + struct synaptics_data *priv = psmouse->private; 582 524 struct psmouse *child = serio_get_drvdata(ptport); 583 525 584 526 if (child && child->state == PSMOUSE_ACTIVATED) { 585 - serio_interrupt(ptport, packet[1], 0); 527 + serio_interrupt(ptport, packet[1] | priv->pt_buttons, 0); 586 528 serio_interrupt(ptport, packet[4], 0); 587 529 serio_interrupt(ptport, packet[5], 0); 588 530 if (child->pktsize == 4) 589 531 serio_interrupt(ptport, packet[2], 0); 590 - } else 532 + } else { 591 533 serio_interrupt(ptport, packet[1], 0); 534 + } 592 535 } 593 536 594 537 static void synaptics_pt_activate(struct psmouse *psmouse) ··· 668 603 default: 669 604 break; 670 605 } 606 + } 607 + 608 + static void synaptics_parse_ext_buttons(const unsigned char buf[], 609 + struct synaptics_data *priv, 610 + struct synaptics_hw_state *hw) 611 + { 612 + unsigned int ext_bits = 613 + (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; 614 + unsigned int ext_mask = GENMASK(ext_bits - 1, 0); 615 + 616 + hw->ext_buttons = buf[4] & ext_mask; 617 + hw->ext_buttons |= (buf[5] & ext_mask) << ext_bits; 671 618 } 672 619 673 620 static bool is_forcepad; ··· 768 691 hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0; 769 692 } 770 693 771 - if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) && 694 + if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) > 0 && 772 695 ((buf[0] ^ buf[3]) & 0x02)) { 773 - switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) { 774 - default: 775 - /* 776 - * if nExtBtn is greater than 8 it should be 777 - * considered invalid and treated as 0 778 - */ 779 - break; 780 - case 8: 781 - hw->ext_buttons |= ((buf[5] & 0x08)) ? 0x80 : 0; 782 - hw->ext_buttons |= ((buf[4] & 0x08)) ? 0x40 : 0; 783 - case 6: 784 - hw->ext_buttons |= ((buf[5] & 0x04)) ? 0x20 : 0; 785 - hw->ext_buttons |= ((buf[4] & 0x04)) ? 0x10 : 0; 786 - case 4: 787 - hw->ext_buttons |= ((buf[5] & 0x02)) ? 0x08 : 0; 788 - hw->ext_buttons |= ((buf[4] & 0x02)) ? 0x04 : 0; 789 - case 2: 790 - hw->ext_buttons |= ((buf[5] & 0x01)) ? 0x02 : 0; 791 - hw->ext_buttons |= ((buf[4] & 0x01)) ? 0x01 : 0; 792 - } 696 + synaptics_parse_ext_buttons(buf, priv, hw); 793 697 } 794 698 } else { 795 699 hw->x = (((buf[1] & 0x1f) << 8) | buf[2]); ··· 832 774 } 833 775 } 834 776 777 + static void synaptics_report_ext_buttons(struct psmouse *psmouse, 778 + const struct synaptics_hw_state *hw) 779 + { 780 + struct input_dev *dev = psmouse->dev; 781 + struct synaptics_data *priv = psmouse->private; 782 + int ext_bits = (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) + 1) >> 1; 783 + char buf[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 784 + int i; 785 + 786 + if (!SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)) 787 + return; 788 + 789 + /* Bug in FW 8.1, buttons are reported only when ExtBit is 1 */ 790 + if (SYN_ID_FULL(priv->identity) == 0x801 && 791 + !((psmouse->packet[0] ^ psmouse->packet[3]) & 0x02)) 792 + return; 793 + 794 + if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) { 795 + for (i = 0; i < ext_bits; i++) { 796 + input_report_key(dev, BTN_0 + 2 * i, 797 + hw->ext_buttons & (1 << i)); 798 + input_report_key(dev, BTN_1 + 2 * i, 799 + hw->ext_buttons & (1 << (i + ext_bits))); 800 + } 801 + return; 802 + } 803 + 804 + /* 805 + * This generation of touchpads has the trackstick buttons 806 + * physically wired to the touchpad. Re-route them through 807 + * the pass-through interface. 808 + */ 809 + if (!priv->pt_port) 810 + return; 811 + 812 + /* The trackstick expects at most 3 buttons */ 813 + priv->pt_buttons = SYN_CAP_EXT_BUTTON_STICK_L(hw->ext_buttons) | 814 + SYN_CAP_EXT_BUTTON_STICK_R(hw->ext_buttons) << 1 | 815 + SYN_CAP_EXT_BUTTON_STICK_M(hw->ext_buttons) << 2; 816 + 817 + synaptics_pass_pt_packet(psmouse, priv->pt_port, buf); 818 + } 819 + 835 820 static void synaptics_report_buttons(struct psmouse *psmouse, 836 821 const struct synaptics_hw_state *hw) 837 822 { 838 823 struct input_dev *dev = psmouse->dev; 839 824 struct synaptics_data *priv = psmouse->private; 840 - int i; 841 825 842 826 input_report_key(dev, BTN_LEFT, hw->left); 843 827 input_report_key(dev, BTN_RIGHT, hw->right); ··· 892 792 input_report_key(dev, BTN_BACK, hw->down); 893 793 } 894 794 895 - for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) 896 - input_report_key(dev, BTN_0 + i, hw->ext_buttons & (1 << i)); 795 + synaptics_report_ext_buttons(psmouse, hw); 897 796 } 898 797 899 798 static void synaptics_report_mt_data(struct psmouse *psmouse, ··· 912 813 pos[i].y = synaptics_invert_y(hw[i]->y); 913 814 } 914 815 915 - input_mt_assign_slots(dev, slot, pos, nsemi, DMAX * priv->x_res); 816 + input_mt_assign_slots(dev, slot, pos, nsemi, 0); 916 817 917 818 for (i = 0; i < nsemi; i++) { 918 819 input_mt_slot(dev, slot[i]); ··· 1113 1014 if (SYN_CAP_PASS_THROUGH(priv->capabilities) && 1114 1015 synaptics_is_pt_packet(psmouse->packet)) { 1115 1016 if (priv->pt_port) 1116 - synaptics_pass_pt_packet(priv->pt_port, psmouse->packet); 1017 + synaptics_pass_pt_packet(psmouse, priv->pt_port, 1018 + psmouse->packet); 1117 1019 } else 1118 1020 synaptics_process_packet(psmouse); 1119 1021 ··· 1216 1116 __set_bit(BTN_BACK, dev->keybit); 1217 1117 } 1218 1118 1219 - for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) 1220 - __set_bit(BTN_0 + i, dev->keybit); 1119 + if (!SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) 1120 + for (i = 0; i < SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap); i++) 1121 + __set_bit(BTN_0 + i, dev->keybit); 1221 1122 1222 1123 __clear_bit(EV_REL, dev->evbit); 1223 1124 __clear_bit(REL_X, dev->relbit); ··· 1226 1125 1227 1126 if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { 1228 1127 __set_bit(INPUT_PROP_BUTTONPAD, dev->propbit); 1229 - if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids)) 1128 + if (psmouse_matches_pnp_id(psmouse, topbuttonpad_pnp_ids) && 1129 + !SYN_CAP_EXT_BUTTONS_STICK(priv->ext_cap_10)) 1230 1130 __set_bit(INPUT_PROP_TOPBUTTONPAD, dev->propbit); 1231 1131 /* Clickpads report only left button */ 1232 1132 __clear_bit(BTN_RIGHT, dev->keybit);
+28
drivers/input/mouse/synaptics.h
··· 22 22 #define SYN_QUE_EXT_CAPAB_0C 0x0c 23 23 #define SYN_QUE_EXT_MAX_COORDS 0x0d 24 24 #define SYN_QUE_EXT_MIN_COORDS 0x0f 25 + #define SYN_QUE_MEXT_CAPAB_10 0x10 25 26 26 27 /* synatics modes */ 27 28 #define SYN_BIT_ABSOLUTE_MODE (1 << 7) ··· 54 53 #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) 55 54 #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) 56 55 #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) 56 + #define SYN_MEXT_CAP_BIT(m) ((m) & (1 << 1)) 57 57 58 58 /* 59 59 * The following describes response for the 0x0c query. ··· 90 88 #define SYN_CAP_ADV_GESTURE(ex0c) ((ex0c) & 0x080000) 91 89 #define SYN_CAP_REDUCED_FILTERING(ex0c) ((ex0c) & 0x000400) 92 90 #define SYN_CAP_IMAGE_SENSOR(ex0c) ((ex0c) & 0x000800) 91 + 92 + /* 93 + * The following descibes response for the 0x10 query. 94 + * 95 + * byte mask name meaning 96 + * ---- ---- ------- ------------ 97 + * 1 0x01 ext buttons are stick buttons exported in the extended 98 + * capability are actually meant to be used 99 + * by the tracktick (pass-through). 100 + * 1 0x02 SecurePad the touchpad is a SecurePad, so it 101 + * contains a built-in fingerprint reader. 102 + * 1 0xe0 more ext count how many more extented queries are 103 + * available after this one. 104 + * 2 0xff SecurePad width the width of the SecurePad fingerprint 105 + * reader. 106 + * 3 0xff SecurePad height the height of the SecurePad fingerprint 107 + * reader. 108 + */ 109 + #define SYN_CAP_EXT_BUTTONS_STICK(ex10) ((ex10) & 0x010000) 110 + #define SYN_CAP_SECUREPAD(ex10) ((ex10) & 0x020000) 111 + 112 + #define SYN_CAP_EXT_BUTTON_STICK_L(eb) (!!((eb) & 0x01)) 113 + #define SYN_CAP_EXT_BUTTON_STICK_M(eb) (!!((eb) & 0x02)) 114 + #define SYN_CAP_EXT_BUTTON_STICK_R(eb) (!!((eb) & 0x04)) 93 115 94 116 /* synaptics modes query bits */ 95 117 #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) ··· 169 143 unsigned long int capabilities; /* Capabilities */ 170 144 unsigned long int ext_cap; /* Extended Capabilities */ 171 145 unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ 146 + unsigned long int ext_cap_10; /* Ext Caps from 0x10 query */ 172 147 unsigned long int identity; /* Identification */ 173 148 unsigned int x_res, y_res; /* X/Y resolution in units/mm */ 174 149 unsigned int x_max, y_max; /* Max coordinates (from FW) */ ··· 183 156 bool disable_gesture; /* disable gestures */ 184 157 185 158 struct serio *pt_port; /* Pass-through serio port */ 159 + unsigned char pt_buttons; /* Pass-through buttons */ 186 160 187 161 /* 188 162 * Last received Advanced Gesture Mode (AGM) packet. An AGM packet