Commit 427a5746b4215b154efb85b07781799b79f8958c
Committed by
Greg Kroah-Hartman
1 parent
ce9555406a
HID: rmi: Check for additional ACM registers appended to F11 data report
commit 8414947a2018a98cf3adc975dc279f41ba30ab11 upstream. If a touchpad reports the F11 data40 register then this indicates that the touchpad reports additional ACM (Accidental Contact Mitigation) data after the F11 data in the HID attention report. These additional bytes shift the position of the F30 button data causing the driver to incorrectly report button state when this functionality is present. This patch accounts for the additional data in the report. Fixes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1398533 Signed-off-by: Andrew Duggan <aduggan@synaptics.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz> Cc: Joseph Salisbury <joseph.salisbury@canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 52 additions and 9 deletions Side-by-side Diff
drivers/hid/hid-rmi.c
... | ... | @@ -584,11 +584,15 @@ |
584 | 584 | bool has_query10 = false; |
585 | 585 | bool has_query11; |
586 | 586 | bool has_query12; |
587 | + bool has_query27; | |
588 | + bool has_query28; | |
589 | + bool has_query36 = false; | |
587 | 590 | bool has_physical_props; |
588 | 591 | bool has_gestures; |
589 | 592 | bool has_rel; |
593 | + bool has_data40 = false; | |
590 | 594 | unsigned x_size, y_size; |
591 | - u16 query12_offset; | |
595 | + u16 query_offset; | |
592 | 596 | |
593 | 597 | if (!data->f11.query_base_addr) { |
594 | 598 | hid_err(hdev, "No 2D sensor found, giving up.\n"); |
... | ... | @@ -604,6 +608,8 @@ |
604 | 608 | has_query9 = !!(buf[0] & BIT(3)); |
605 | 609 | has_query11 = !!(buf[0] & BIT(4)); |
606 | 610 | has_query12 = !!(buf[0] & BIT(5)); |
611 | + has_query27 = !!(buf[0] & BIT(6)); | |
612 | + has_query28 = !!(buf[0] & BIT(7)); | |
607 | 613 | |
608 | 614 | /* query 1 to get the max number of fingers */ |
609 | 615 | ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); |
610 | 616 | |
611 | 617 | |
612 | 618 | |
613 | 619 | |
614 | 620 | |
615 | 621 | |
... | ... | @@ -642,27 +648,27 @@ |
642 | 648 | * +1 for query 5 which is present since absolute events are |
643 | 649 | * reported and +1 for query 12. |
644 | 650 | */ |
645 | - query12_offset = 6; | |
651 | + query_offset = 6; | |
646 | 652 | |
647 | 653 | if (has_rel) |
648 | - ++query12_offset; /* query 6 is present */ | |
654 | + ++query_offset; /* query 6 is present */ | |
649 | 655 | |
650 | 656 | if (has_gestures) |
651 | - query12_offset += 2; /* query 7 and 8 are present */ | |
657 | + query_offset += 2; /* query 7 and 8 are present */ | |
652 | 658 | |
653 | 659 | if (has_query9) |
654 | - ++query12_offset; | |
660 | + ++query_offset; | |
655 | 661 | |
656 | 662 | if (has_query10) |
657 | - ++query12_offset; | |
663 | + ++query_offset; | |
658 | 664 | |
659 | 665 | if (has_query11) |
660 | - ++query12_offset; | |
666 | + ++query_offset; | |
661 | 667 | |
662 | 668 | /* query 12 to know if the physical properties are reported */ |
663 | 669 | if (has_query12) { |
664 | 670 | ret = rmi_read(hdev, data->f11.query_base_addr |
665 | - + query12_offset, buf); | |
671 | + + query_offset, buf); | |
666 | 672 | if (ret) { |
667 | 673 | hid_err(hdev, "can not get query 12: %d.\n", ret); |
668 | 674 | return ret; |
669 | 675 | |
... | ... | @@ -670,9 +676,10 @@ |
670 | 676 | has_physical_props = !!(buf[0] & BIT(5)); |
671 | 677 | |
672 | 678 | if (has_physical_props) { |
679 | + query_offset += 1; | |
673 | 680 | ret = rmi_read_block(hdev, |
674 | 681 | data->f11.query_base_addr |
675 | - + query12_offset + 1, buf, 4); | |
682 | + + query_offset, buf, 4); | |
676 | 683 | if (ret) { |
677 | 684 | hid_err(hdev, "can not read query 15-18: %d.\n", |
678 | 685 | ret); |
679 | 686 | |
... | ... | @@ -687,8 +694,44 @@ |
687 | 694 | |
688 | 695 | hid_info(hdev, "%s: size in mm: %d x %d\n", |
689 | 696 | __func__, data->x_size_mm, data->y_size_mm); |
697 | + | |
698 | + /* | |
699 | + * query 15 - 18 contain the size of the sensor | |
700 | + * and query 19 - 26 contain bezel dimensions | |
701 | + */ | |
702 | + query_offset += 12; | |
690 | 703 | } |
691 | 704 | } |
705 | + | |
706 | + if (has_query27) | |
707 | + ++query_offset; | |
708 | + | |
709 | + if (has_query28) { | |
710 | + ret = rmi_read(hdev, data->f11.query_base_addr | |
711 | + + query_offset, buf); | |
712 | + if (ret) { | |
713 | + hid_err(hdev, "can not get query 28: %d.\n", ret); | |
714 | + return ret; | |
715 | + } | |
716 | + | |
717 | + has_query36 = !!(buf[0] & BIT(6)); | |
718 | + } | |
719 | + | |
720 | + if (has_query36) { | |
721 | + query_offset += 2; | |
722 | + ret = rmi_read(hdev, data->f11.query_base_addr | |
723 | + + query_offset, buf); | |
724 | + if (ret) { | |
725 | + hid_err(hdev, "can not get query 36: %d.\n", ret); | |
726 | + return ret; | |
727 | + } | |
728 | + | |
729 | + has_data40 = !!(buf[0] & BIT(5)); | |
730 | + } | |
731 | + | |
732 | + | |
733 | + if (has_data40) | |
734 | + data->f11.report_size += data->max_fingers * 2; | |
692 | 735 | |
693 | 736 | /* |
694 | 737 | * retrieve the ctrl registers |