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

Input: elantech - add v4 hardware support

v4 hardware is a true multitouch capable touchpad (up to 5 fingers).
The packet format is quite complex, please see protocol document for
reference.

Signed-off-by: JJ Ding <jj_ding@emc.com.tw>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

authored by

JJ Ding and committed by
Dmitry Torokhov
1dc6edec 28f49616

+432 -16
+170
Documentation/input/elantech.txt
··· 32 32 6.2 Native absolute mode 6 byte packet format 33 33 6.2.1 One/Three finger touch 34 34 6.2.2 Two finger touch 35 + 7. Hardware version 4 36 + 7.1 Registers 37 + 7.2 Native absolute mode 6 byte packet format 38 + 7.2.1 Status packet 39 + 7.2.2 Head packet 40 + 7.2.3 Motion packet 35 41 36 42 37 43 ··· 579 573 sends two 6 byte packets. The first packet contains data for the first finger, 580 574 the second packet has data for the second finger. So for two finger touch a 581 575 total of 12 bytes are sent. 576 + 577 + ///////////////////////////////////////////////////////////////////////////// 578 + 579 + 7. Hardware version 4 580 + ================== 581 + 582 + 7.1 Registers 583 + ~~~~~~~~~ 584 + * reg_07 585 + 586 + bit 7 6 5 4 3 2 1 0 587 + 0 0 0 0 0 0 0 A 588 + 589 + A: 1 = enable absolute tracking 590 + 591 + 7.2 Native absolute mode 6 byte packet format 592 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 593 + v4 hardware is a true multitouch touchpad, capable of tracking up to 5 fingers. 594 + Unfortunately, due to PS/2's limited bandwidth, its packet format is rather 595 + complex. 596 + 597 + Whenever the numbers or identities of the fingers changes, the hardware sends a 598 + status packet to indicate how many and which fingers is on touchpad, followed by 599 + head packets or motion packets. A head packet contains data of finger id, finger 600 + position (absolute x, y values), width, and pressure. A motion packet contains 601 + two fingers' position delta. 602 + 603 + For example, when status packet tells there are 2 fingers on touchpad, then we 604 + can expect two following head packets. If the finger status doesn't change, 605 + the following packets would be motion packets, only sending delta of finger 606 + position, until we receive a status packet. 607 + 608 + One exception is one finger touch. when a status packet tells us there is only 609 + one finger, the hardware would just send head packets afterwards. 610 + 611 + 7.2.1 Status packet 612 + ~~~~~~~~~~~~~ 613 + 614 + byte 0: 615 + 616 + bit 7 6 5 4 3 2 1 0 617 + . . . . 0 1 R L 618 + 619 + L, R = 1 when Left, Right mouse button pressed 620 + 621 + byte 1: 622 + 623 + bit 7 6 5 4 3 2 1 0 624 + . . . ft4 ft3 ft2 ft1 ft0 625 + 626 + ft4 ft3 ft2 ft1 ft0 ftn = 1 when finger n is on touchpad 627 + 628 + byte 2: not used 629 + 630 + byte 3: 631 + 632 + bit 7 6 5 4 3 2 1 0 633 + . . . 1 0 0 0 0 634 + 635 + constant bits 636 + 637 + byte 4: 638 + 639 + bit 7 6 5 4 3 2 1 0 640 + p . . . . . . . 641 + 642 + p = 1 for palm 643 + 644 + byte 5: not used 645 + 646 + 7.2.2 Head packet 647 + ~~~~~~~~~~~ 648 + 649 + byte 0: 650 + 651 + bit 7 6 5 4 3 2 1 0 652 + w3 w2 w1 w0 0 1 R L 653 + 654 + L, R = 1 when Left, Right mouse button pressed 655 + w3..w0 = finger width (spans how many trace lines) 656 + 657 + byte 1: 658 + 659 + bit 7 6 5 4 3 2 1 0 660 + p7 p6 p5 p4 x11 x10 x9 x8 661 + 662 + byte 2: 663 + 664 + bit 7 6 5 4 3 2 1 0 665 + x7 x6 x5 x4 x3 x2 x1 x0 666 + 667 + x11..x0 = absolute x value (horizontal) 668 + 669 + byte 3: 670 + 671 + bit 7 6 5 4 3 2 1 0 672 + id2 id1 id0 1 0 0 0 1 673 + 674 + id2..id0 = finger id 675 + 676 + byte 4: 677 + 678 + bit 7 6 5 4 3 2 1 0 679 + p3 p1 p2 p0 y11 y10 y9 y8 680 + 681 + p7..p0 = pressure 682 + 683 + byte 5: 684 + 685 + bit 7 6 5 4 3 2 1 0 686 + y7 y6 y5 y4 y3 y2 y1 y0 687 + 688 + y11..y0 = absolute y value (vertical) 689 + 690 + 7.2.3 Motion packet 691 + ~~~~~~~~~~~~~ 692 + 693 + byte 0: 694 + 695 + bit 7 6 5 4 3 2 1 0 696 + id2 id1 id0 w 0 1 R L 697 + 698 + L, R = 1 when Left, Right mouse button pressed 699 + id2..id0 = finger id 700 + w = 1 when delta overflows (> 127 or < -128), in this case 701 + firmware sends us (delta x / 5) and (delta y / 5) 702 + 703 + byte 1: 704 + 705 + bit 7 6 5 4 3 2 1 0 706 + x7 x6 x5 x4 x3 x2 x1 x0 707 + 708 + x7..x0 = delta x (two's complement) 709 + 710 + byte 2: 711 + 712 + bit 7 6 5 4 3 2 1 0 713 + y7 y6 y5 y4 y3 y2 y1 y0 714 + 715 + y7..y0 = delta y (two's complement) 716 + 717 + byte 3: 718 + 719 + bit 7 6 5 4 3 2 1 0 720 + id2 id1 id0 1 0 0 1 0 721 + 722 + id2..id0 = finger id 723 + 724 + byte 4: 725 + 726 + bit 7 6 5 4 3 2 1 0 727 + x7 x6 x5 x4 x3 x2 x1 x0 728 + 729 + x7..x0 = delta x (two's complement) 730 + 731 + byte 5: 732 + 733 + bit 7 6 5 4 3 2 1 0 734 + y7 y6 y5 y4 y3 y2 y1 y0 735 + 736 + y7..y0 = delta y (two's complement) 737 + 738 + byte 0 ~ 2 for one finger 739 + byte 3 ~ 5 for another
+236 -13
drivers/input/mouse/elantech.c
··· 84 84 unsigned char param[3]; 85 85 int rc = 0; 86 86 87 - if (reg < 0x10 || reg > 0x26) 87 + if (reg < 0x07 || reg > 0x26) 88 88 return -1; 89 89 90 90 if (reg > 0x11 && reg < 0x20) ··· 109 109 } 110 110 break; 111 111 112 - case 3: 112 + case 3 ... 4: 113 113 if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 114 114 elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || 115 115 elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || ··· 122 122 123 123 if (rc) 124 124 pr_err("failed to read register 0x%02x.\n", reg); 125 - else 125 + else if (etd->hw_version != 4) 126 126 *val = param[0]; 127 + else 128 + *val = param[1]; 127 129 128 130 return rc; 129 131 } ··· 139 137 struct elantech_data *etd = psmouse->private; 140 138 int rc = 0; 141 139 142 - if (reg < 0x10 || reg > 0x26) 140 + if (reg < 0x07 || reg > 0x26) 143 141 return -1; 144 142 145 143 if (reg > 0x11 && reg < 0x20) ··· 172 170 elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || 173 171 elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 174 172 elantech_ps2_command(psmouse, NULL, reg) || 173 + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 174 + elantech_ps2_command(psmouse, NULL, val) || 175 + elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { 176 + rc = -1; 177 + } 178 + break; 179 + 180 + case 4: 181 + if (elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 182 + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || 183 + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 184 + elantech_ps2_command(psmouse, NULL, reg) || 185 + elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 186 + elantech_ps2_command(psmouse, NULL, ETP_REGISTER_READWRITE) || 175 187 elantech_ps2_command(psmouse, NULL, ETP_PS2_CUSTOM_COMMAND) || 176 188 elantech_ps2_command(psmouse, NULL, val) || 177 189 elantech_ps2_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11)) { ··· 425 409 * byte 1: . . . . ax11 ax10 ax9 ax8 426 410 * byte 2: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 427 411 */ 428 - etd->prev_x = ((packet[1] & 0x0f) << 8) | packet[2]; 412 + etd->mt[0].x = ((packet[1] & 0x0f) << 8) | packet[2]; 429 413 /* 430 414 * byte 4: . . . . ay11 ay10 ay9 ay8 431 415 * byte 5: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 432 416 */ 433 - etd->prev_y = etd->y_max - 417 + etd->mt[0].y = etd->y_max - 434 418 (((packet[4] & 0x0f) << 8) | packet[5]); 435 419 /* 436 420 * wait for next packet ··· 439 423 } 440 424 441 425 /* packet_type == PACKET_V3_TAIL */ 442 - x1 = etd->prev_x; 443 - y1 = etd->prev_y; 426 + x1 = etd->mt[0].x; 427 + y1 = etd->mt[0].y; 444 428 x2 = ((packet[1] & 0x0f) << 8) | packet[2]; 445 429 y2 = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); 446 430 break; ··· 464 448 input_report_abs(dev, ABS_TOOL_WIDTH, width); 465 449 466 450 input_sync(dev); 451 + } 452 + 453 + static void elantech_input_sync_v4(struct psmouse *psmouse) 454 + { 455 + struct input_dev *dev = psmouse->dev; 456 + unsigned char *packet = psmouse->packet; 457 + 458 + input_report_key(dev, BTN_LEFT, packet[0] & 0x01); 459 + input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); 460 + input_mt_report_pointer_emulation(dev, true); 461 + input_sync(dev); 462 + } 463 + 464 + static void process_packet_status_v4(struct psmouse *psmouse) 465 + { 466 + struct input_dev *dev = psmouse->dev; 467 + unsigned char *packet = psmouse->packet; 468 + unsigned fingers; 469 + int i; 470 + 471 + /* notify finger state change */ 472 + fingers = packet[1] & 0x1f; 473 + for (i = 0; i < ETP_MAX_FINGERS; i++) { 474 + if ((fingers & (1 << i)) == 0) { 475 + input_mt_slot(dev, i); 476 + input_mt_report_slot_state(dev, MT_TOOL_FINGER, false); 477 + } 478 + } 479 + 480 + elantech_input_sync_v4(psmouse); 481 + } 482 + 483 + static void process_packet_head_v4(struct psmouse *psmouse) 484 + { 485 + struct input_dev *dev = psmouse->dev; 486 + struct elantech_data *etd = psmouse->private; 487 + unsigned char *packet = psmouse->packet; 488 + int id = ((packet[3] & 0xe0) >> 5) - 1; 489 + int pres, traces; 490 + 491 + if (id < 0) 492 + return; 493 + 494 + etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; 495 + etd->mt[id].y = etd->y_max - (((packet[4] & 0x0f) << 8) | packet[5]); 496 + pres = (packet[1] & 0xf0) | ((packet[4] & 0xf0) >> 4); 497 + traces = (packet[0] & 0xf0) >> 4; 498 + 499 + input_mt_slot(dev, id); 500 + input_mt_report_slot_state(dev, MT_TOOL_FINGER, true); 501 + 502 + input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); 503 + input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); 504 + input_report_abs(dev, ABS_MT_PRESSURE, pres); 505 + input_report_abs(dev, ABS_MT_TOUCH_MAJOR, traces * etd->width); 506 + /* report this for backwards compatibility */ 507 + input_report_abs(dev, ABS_TOOL_WIDTH, traces); 508 + 509 + elantech_input_sync_v4(psmouse); 510 + } 511 + 512 + static void process_packet_motion_v4(struct psmouse *psmouse) 513 + { 514 + struct input_dev *dev = psmouse->dev; 515 + struct elantech_data *etd = psmouse->private; 516 + unsigned char *packet = psmouse->packet; 517 + int weight, delta_x1 = 0, delta_y1 = 0, delta_x2 = 0, delta_y2 = 0; 518 + int id, sid; 519 + 520 + id = ((packet[0] & 0xe0) >> 5) - 1; 521 + if (id < 0) 522 + return; 523 + 524 + sid = ((packet[3] & 0xe0) >> 5) - 1; 525 + weight = (packet[0] & 0x10) ? ETP_WEIGHT_VALUE : 1; 526 + /* 527 + * Motion packets give us the delta of x, y values of specific fingers, 528 + * but in two's complement. Let the compiler do the conversion for us. 529 + * Also _enlarge_ the numbers to int, in case of overflow. 530 + */ 531 + delta_x1 = (signed char)packet[1]; 532 + delta_y1 = (signed char)packet[2]; 533 + delta_x2 = (signed char)packet[4]; 534 + delta_y2 = (signed char)packet[5]; 535 + 536 + etd->mt[id].x += delta_x1 * weight; 537 + etd->mt[id].y -= delta_y1 * weight; 538 + input_mt_slot(dev, id); 539 + input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); 540 + input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); 541 + 542 + if (sid >= 0) { 543 + etd->mt[sid].x += delta_x2 * weight; 544 + etd->mt[sid].y -= delta_y2 * weight; 545 + input_mt_slot(dev, sid); 546 + input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[sid].x); 547 + input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[sid].y); 548 + } 549 + 550 + elantech_input_sync_v4(psmouse); 551 + } 552 + 553 + static void elantech_report_absolute_v4(struct psmouse *psmouse, 554 + int packet_type) 555 + { 556 + switch (packet_type) { 557 + case PACKET_V4_STATUS: 558 + process_packet_status_v4(psmouse); 559 + break; 560 + 561 + case PACKET_V4_HEAD: 562 + process_packet_head_v4(psmouse); 563 + break; 564 + 565 + case PACKET_V4_MOTION: 566 + process_packet_motion_v4(psmouse); 567 + break; 568 + 569 + case PACKET_UNKNOWN: 570 + default: 571 + /* impossible to get here */ 572 + break; 573 + } 467 574 } 468 575 469 576 static int elantech_packet_check_v1(struct psmouse *psmouse) ··· 643 504 644 505 /* 645 506 * We check the constant bits to determine what packet type we get, 646 - * so packet checking is mandatory for v3 hardware. 507 + * so packet checking is mandatory for v3 and later hardware. 647 508 */ 648 509 static int elantech_packet_check_v3(struct psmouse *psmouse) 649 510 { ··· 662 523 663 524 if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c) 664 525 return PACKET_V3_TAIL; 526 + 527 + return PACKET_UNKNOWN; 528 + } 529 + 530 + static int elantech_packet_check_v4(struct psmouse *psmouse) 531 + { 532 + unsigned char *packet = psmouse->packet; 533 + 534 + if ((packet[0] & 0x0c) == 0x04 && 535 + (packet[3] & 0x1f) == 0x11) 536 + return PACKET_V4_HEAD; 537 + 538 + if ((packet[0] & 0x0c) == 0x04 && 539 + (packet[3] & 0x1f) == 0x12) 540 + return PACKET_V4_MOTION; 541 + 542 + if ((packet[0] & 0x0c) == 0x04 && 543 + (packet[3] & 0x1f) == 0x10) 544 + return PACKET_V4_STATUS; 665 545 666 546 return PACKET_UNKNOWN; 667 547 } ··· 725 567 726 568 elantech_report_absolute_v3(psmouse, packet_type); 727 569 break; 570 + 571 + case 4: 572 + packet_type = elantech_packet_check_v4(psmouse); 573 + if (packet_type == PACKET_UNKNOWN) 574 + return PSMOUSE_BAD_DATA; 575 + 576 + elantech_report_absolute_v4(psmouse, packet_type); 577 + break; 728 578 } 729 579 730 580 return PSMOUSE_FULL_PACKET; ··· 776 610 rc = -1; 777 611 778 612 break; 613 + 614 + case 4: 615 + etd->reg_07 = 0x01; 616 + if (elantech_write_reg(psmouse, 0x07, etd->reg_07)) 617 + rc = -1; 618 + 619 + goto skip_readback_reg_10; /* v4 has no reg 0x10 to read */ 779 620 } 780 621 781 622 if (rc == 0) { ··· 810 637 } 811 638 } 812 639 640 + skip_readback_reg_10: 813 641 if (rc) 814 642 pr_err("failed to initialise registers.\n"); 815 643 ··· 819 645 820 646 static int elantech_set_range(struct psmouse *psmouse, 821 647 unsigned int *x_min, unsigned int *y_min, 822 - unsigned int *x_max, unsigned int *y_max) 648 + unsigned int *x_max, unsigned int *y_max, 649 + unsigned int *width) 823 650 { 824 651 struct elantech_data *etd = psmouse->private; 825 652 unsigned char param[3]; 653 + unsigned char traces; 826 654 int i; 827 655 828 656 switch (etd->hw_version) { ··· 860 684 *x_max = (0x0f & param[0]) << 8 | param[1]; 861 685 *y_max = (0xf0 & param[0]) << 4 | param[2]; 862 686 break; 687 + 688 + case 4: 689 + if (synaptics_send_cmd(psmouse, ETP_FW_ID_QUERY, param)) 690 + return -1; 691 + 692 + *x_max = (0x0f & param[0]) << 8 | param[1]; 693 + *y_max = (0xf0 & param[0]) << 4 | param[2]; 694 + traces = etd->capabilities[1]; 695 + if ((traces < 2) || (traces > *x_max)) 696 + return -1; 697 + 698 + *width = *x_max / (traces - 1); 699 + break; 863 700 } 864 701 865 702 return 0; ··· 885 696 { 886 697 struct input_dev *dev = psmouse->dev; 887 698 struct elantech_data *etd = psmouse->private; 888 - unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0; 699 + unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0; 889 700 890 - if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max)) 701 + if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width)) 891 702 return -1; 892 703 893 704 __set_bit(EV_KEY, dev->evbit); ··· 931 742 input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); 932 743 input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); 933 744 break; 745 + 746 + case 4: 747 + __set_bit(BTN_TOOL_QUADTAP, dev->keybit); 748 + /* For X to recognize me as touchpad. */ 749 + input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0); 750 + input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0); 751 + /* 752 + * range of pressure and width is the same as v2, 753 + * report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility. 754 + */ 755 + input_set_abs_params(dev, ABS_PRESSURE, ETP_PMIN_V2, 756 + ETP_PMAX_V2, 0, 0); 757 + input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2, 758 + ETP_WMAX_V2, 0, 0); 759 + /* Multitouch capable pad, up to 5 fingers. */ 760 + input_mt_init_slots(dev, ETP_MAX_FINGERS); 761 + input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0); 762 + input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0); 763 + input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2, 764 + ETP_PMAX_V2, 0, 0); 765 + /* 766 + * The firmware reports how many trace lines the finger spans, 767 + * convert to surface unit as Protocol-B requires. 768 + */ 769 + input_set_abs_params(dev, ABS_MT_TOUCH_MAJOR, 0, 770 + ETP_WMAX_V2 * width, 0, 0); 771 + break; 934 772 } 935 773 936 774 etd->y_max = y_max; 775 + etd->width = width; 937 776 938 777 return 0; 939 778 } ··· 1033 816 elantech_show_int_attr, \ 1034 817 elantech_set_int_attr) 1035 818 819 + ELANTECH_INT_ATTR(reg_07, 0x07); 1036 820 ELANTECH_INT_ATTR(reg_10, 0x10); 1037 821 ELANTECH_INT_ATTR(reg_11, 0x11); 1038 822 ELANTECH_INT_ATTR(reg_20, 0x20); ··· 1047 829 ELANTECH_INT_ATTR(paritycheck, 0); 1048 830 1049 831 static struct attribute *elantech_attrs[] = { 832 + &psmouse_attr_reg_07.dattr.attr, 1050 833 &psmouse_attr_reg_10.dattr.attr, 1051 834 &psmouse_attr_reg_11.dattr.attr, 1052 835 &psmouse_attr_reg_20.dattr.attr, ··· 1176 957 */ 1177 958 static int elantech_set_properties(struct elantech_data *etd) 1178 959 { 960 + int ver = (etd->fw_version & 0x0f0000) >> 16; 961 + 1179 962 if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600) 1180 963 etd->hw_version = 1; 1181 964 else if (etd->fw_version < 0x150600) 1182 965 etd->hw_version = 2; 1183 - else if ((etd->fw_version & 0x0f0000) >> 16 == 5) 966 + else if (ver == 5) 1184 967 etd->hw_version = 3; 968 + else if (ver == 6) 969 + etd->hw_version = 4; 1185 970 else 1186 971 return -1; 1187 972
+26 -3
drivers/input/mouse/elantech.h
··· 82 82 #define ETP_WMAX_V2 15 83 83 84 84 /* 85 - * v3 hardware has 2 kinds of packet types. 85 + * v3 hardware has 2 kinds of packet types, 86 + * v4 hardware has 3. 86 87 */ 87 88 #define PACKET_UNKNOWN 0x01 88 89 #define PACKET_DEBOUNCE 0x02 89 90 #define PACKET_V3_HEAD 0x03 90 91 #define PACKET_V3_TAIL 0x04 92 + #define PACKET_V4_HEAD 0x05 93 + #define PACKET_V4_MOTION 0x06 94 + #define PACKET_V4_STATUS 0x07 95 + 96 + /* 97 + * track up to 5 fingers for v4 hardware 98 + */ 99 + #define ETP_MAX_FINGERS 5 100 + 101 + /* 102 + * weight value for v4 hardware 103 + */ 104 + #define ETP_WEIGHT_VALUE 5 105 + 106 + /* 107 + * The base position for one finger, v4 hardware 108 + */ 109 + struct finger_pos { 110 + unsigned int x; 111 + unsigned int y; 112 + }; 91 113 92 114 struct elantech_data { 115 + unsigned char reg_07; 93 116 unsigned char reg_10; 94 117 unsigned char reg_11; 95 118 unsigned char reg_20; ··· 131 108 unsigned int fw_version; 132 109 unsigned int single_finger_reports; 133 110 unsigned int y_max; 134 - unsigned int prev_x; 135 - unsigned int prev_y; 111 + unsigned int width; 112 + struct finger_pos mt[ETP_MAX_FINGERS]; 136 113 unsigned char parity[256]; 137 114 }; 138 115