diff options
| author | Ping Cheng <pingc@wacom.com> | 2010-04-06 02:07:41 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2010-04-14 02:24:56 -0400 |
| commit | ab687b18aa77aeda5472d9ea054bf92c45c49c0c (patch) | |
| tree | 8d103b1aa4827a95d063f0b41b783fddf60eb3d3 /drivers/input | |
| parent | 252f77698fe37bdd784e514820852a3ea9827fd0 (diff) | |
Input: wacom - streamline 2-finger touch support
Clean up 2-finger touch support. This still needs to be converted to
proper multi-touch protocol.
Signed-off-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/tablet/wacom_wac.c | 148 | ||||
| -rw-r--r-- | drivers/input/tablet/wacom_wac.h | 5 |
2 files changed, 80 insertions, 73 deletions
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 950a81d7a67c..847fd0135bcf 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -236,13 +236,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) | |||
| 236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); | 236 | rw = ((data[7] & 0x18) >> 3) - ((data[7] & 0x20) >> 3); |
| 237 | input_report_rel(input, REL_WHEEL, rw); | 237 | input_report_rel(input, REL_WHEEL, rw); |
| 238 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); | 238 | input_report_key(input, BTN_TOOL_FINGER, 0xf0); |
| 239 | input_report_abs(input, ABS_MISC, wacom->id[1]); | ||
| 240 | if (!prox) | 239 | if (!prox) |
| 241 | wacom->id[1] = 0; | 240 | wacom->id[1] = 0; |
| 242 | input_report_abs(input, ABS_MISC, wacom->id[1]); | 241 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
| 243 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | 242 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); |
| 243 | retval = 1; | ||
| 244 | } | 244 | } |
| 245 | retval = 1; | ||
| 246 | break; | 245 | break; |
| 247 | 246 | ||
| 248 | case WACOM_MO: | 247 | case WACOM_MO: |
| @@ -616,43 +615,59 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) | |||
| 616 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) | 615 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx) |
| 617 | { | 616 | { |
| 618 | struct input_dev *input = wacom->input; | 617 | struct input_dev *input = wacom->input; |
| 618 | int finger = idx + 1; | ||
| 619 | int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff; | ||
| 620 | int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff; | ||
| 621 | |||
| 622 | /* | ||
| 623 | * Work around input core suppressing "duplicate" events since | ||
| 624 | * we are abusing ABS_X/ABS_Y to transmit multi-finger data. | ||
| 625 | * This should go away once we switch to true multitouch | ||
| 626 | * protocol. | ||
| 627 | */ | ||
| 628 | if (wacom->last_finger != finger) { | ||
| 629 | if (x == input->abs[ABS_X]) | ||
| 630 | x++; | ||
| 631 | |||
| 632 | if (y == input->abs[ABS_Y]) | ||
| 633 | y++; | ||
| 634 | } | ||
| 619 | 635 | ||
| 620 | input_report_abs(input, ABS_X, | 636 | input_report_abs(input, ABS_X, x); |
| 621 | data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); | 637 | input_report_abs(input, ABS_Y, y); |
| 622 | input_report_abs(input, ABS_Y, | ||
| 623 | data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); | ||
| 624 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 638 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
| 625 | input_report_key(input, wacom->tool[idx], 1); | 639 | input_report_key(input, wacom->tool[finger], 1); |
| 626 | if (idx) | 640 | if (!idx) |
| 627 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 628 | else | ||
| 629 | input_report_key(input, BTN_TOUCH, 1); | 641 | input_report_key(input, BTN_TOUCH, 1); |
| 642 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
| 643 | input_sync(wacom->input); | ||
| 644 | |||
| 645 | wacom->last_finger = finger; | ||
| 630 | } | 646 | } |
| 631 | 647 | ||
| 632 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) | 648 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx) |
| 633 | { | 649 | { |
| 634 | struct input_dev *input = wacom->input; | 650 | struct input_dev *input = wacom->input; |
| 651 | int finger = idx + 1; | ||
| 635 | 652 | ||
| 636 | input_report_abs(input, ABS_X, 0); | 653 | input_report_abs(input, ABS_X, 0); |
| 637 | input_report_abs(input, ABS_Y, 0); | 654 | input_report_abs(input, ABS_Y, 0); |
| 638 | input_report_abs(input, ABS_MISC, 0); | 655 | input_report_abs(input, ABS_MISC, 0); |
| 639 | input_report_key(input, wacom->tool[idx], 0); | 656 | input_report_key(input, wacom->tool[finger], 0); |
| 640 | if (idx) | 657 | if (!idx) |
| 641 | input_event(input, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 642 | else | ||
| 643 | input_report_key(input, BTN_TOUCH, 0); | 658 | input_report_key(input, BTN_TOUCH, 0); |
| 659 | input_event(input, EV_MSC, MSC_SERIAL, finger); | ||
| 660 | input_sync(input); | ||
| 644 | } | 661 | } |
| 645 | 662 | ||
| 646 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) | 663 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) |
| 647 | { | 664 | { |
| 648 | char *data = wacom->data; | 665 | char *data = wacom->data; |
| 649 | struct input_dev *input = wacom->input; | 666 | struct input_dev *input = wacom->input; |
| 650 | static int firstFinger = 0; | ||
| 651 | static int secondFinger = 0; | ||
| 652 | 667 | ||
| 653 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | 668 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; |
| 654 | wacom->id[0] = TOUCH_DEVICE_ID; | 669 | wacom->id[0] = TOUCH_DEVICE_ID; |
| 655 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | 670 | wacom->tool[2] = BTN_TOOL_TRIPLETAP; |
| 656 | 671 | ||
| 657 | if (len != WACOM_PKGLEN_TPC1FG) { | 672 | if (len != WACOM_PKGLEN_TPC1FG) { |
| 658 | 673 | ||
| @@ -664,45 +679,29 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len) | |||
| 664 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); | 679 | input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6])); |
| 665 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); | 680 | input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6])); |
| 666 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 681 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
| 667 | input_report_key(input, wacom->tool[0], 1); | 682 | input_report_key(input, wacom->tool[1], 1); |
| 683 | input_sync(input); | ||
| 668 | break; | 684 | break; |
| 669 | 685 | ||
| 670 | case WACOM_REPORT_TPC2FG: | 686 | case WACOM_REPORT_TPC2FG: |
| 671 | /* keep this byte to send proper out-prox event */ | 687 | if (data[1] & 0x01) |
| 672 | wacom->id[1] = data[1] & 0x03; | ||
| 673 | |||
| 674 | if (data[1] & 0x01) { | ||
| 675 | wacom_tpc_finger_in(wacom, data, 0); | 688 | wacom_tpc_finger_in(wacom, data, 0); |
| 676 | firstFinger = 1; | 689 | else if (wacom->id[1] & 0x01) |
| 677 | } else if (firstFinger) { | ||
| 678 | wacom_tpc_touch_out(wacom, 0); | 690 | wacom_tpc_touch_out(wacom, 0); |
| 679 | } | ||
| 680 | |||
| 681 | if (data[1] & 0x02) { | ||
| 682 | /* sync first finger data */ | ||
| 683 | if (firstFinger) | ||
| 684 | input_sync(input); | ||
| 685 | 691 | ||
| 692 | if (data[1] & 0x02) | ||
| 686 | wacom_tpc_finger_in(wacom, data, 1); | 693 | wacom_tpc_finger_in(wacom, data, 1); |
| 687 | secondFinger = 1; | 694 | else if (wacom->id[1] & 0x02) |
| 688 | } else if (secondFinger) { | ||
| 689 | /* sync first finger data */ | ||
| 690 | if (firstFinger) | ||
| 691 | input_sync(input); | ||
| 692 | |||
| 693 | wacom_tpc_touch_out(wacom, 1); | 695 | wacom_tpc_touch_out(wacom, 1); |
| 694 | secondFinger = 0; | ||
| 695 | } | ||
| 696 | if (!(data[1] & 0x01)) | ||
| 697 | firstFinger = 0; | ||
| 698 | break; | 696 | break; |
| 699 | } | 697 | } |
| 700 | } else { | 698 | } else { |
| 701 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); | 699 | input_report_abs(input, ABS_X, get_unaligned_le16(&data[1])); |
| 702 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); | 700 | input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3])); |
| 703 | input_report_key(input, BTN_TOUCH, 1); | 701 | input_report_key(input, BTN_TOUCH, 1); |
| 704 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 702 | input_report_abs(input, ABS_MISC, wacom->id[1]); |
| 705 | input_report_key(input, wacom->tool[0], 1); | 703 | input_report_key(input, wacom->tool[1], 1); |
| 704 | input_sync(input); | ||
| 706 | } | 705 | } |
| 707 | } | 706 | } |
| 708 | 707 | ||
| @@ -711,13 +710,26 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 711 | struct wacom_features *features = &wacom->features; | 710 | struct wacom_features *features = &wacom->features; |
| 712 | char *data = wacom->data; | 711 | char *data = wacom->data; |
| 713 | struct input_dev *input = wacom->input; | 712 | struct input_dev *input = wacom->input; |
| 714 | int prox = 0, pressure, idx = -1; | 713 | int prox = 0, pressure; |
| 714 | int retval = 0; | ||
| 715 | 715 | ||
| 716 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 716 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
| 717 | 717 | ||
| 718 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ | 718 | if (len == WACOM_PKGLEN_TPC1FG || /* single touch */ |
| 719 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ | 719 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ |
| 720 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ | 720 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ |
| 721 | |||
| 722 | if (wacom->shared->stylus_in_proximity) { | ||
| 723 | if (wacom->id[1] & 0x01) | ||
| 724 | wacom_tpc_touch_out(wacom, 0); | ||
| 725 | |||
| 726 | if (wacom->id[1] & 0x02) | ||
| 727 | wacom_tpc_touch_out(wacom, 1); | ||
| 728 | |||
| 729 | wacom->id[1] = 0; | ||
| 730 | return 0; | ||
| 731 | } | ||
| 732 | |||
| 721 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ | 733 | if (len == WACOM_PKGLEN_TPC1FG) { /* with touch */ |
| 722 | prox = data[0] & 0x01; | 734 | prox = data[0] & 0x01; |
| 723 | } else { /* with capacity */ | 735 | } else { /* with capacity */ |
| @@ -729,36 +741,30 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 729 | prox = data[1] & 0x03; | 741 | prox = data[1] & 0x03; |
| 730 | } | 742 | } |
| 731 | 743 | ||
| 732 | if (!wacom->shared->stylus_in_proximity) { | 744 | if (prox) { |
| 733 | if (prox) { | 745 | if (!wacom->id[1]) |
| 734 | wacom_tpc_touch_in(wacom, len); | 746 | wacom->last_finger = 1; |
| 735 | } else { | 747 | wacom_tpc_touch_in(wacom, len); |
| 736 | if (data[0] == WACOM_REPORT_TPC2FG) { | 748 | } else { |
| 737 | /* 2FGT out-prox */ | 749 | if (data[0] == WACOM_REPORT_TPC2FG) { |
| 738 | idx = (wacom->id[1] & 0x01) - 1; | 750 | /* 2FGT out-prox */ |
| 739 | if (idx == 0) { | 751 | if (wacom->id[1] & 0x01) |
| 740 | wacom_tpc_touch_out(wacom, idx); | ||
| 741 | /* sync first finger event */ | ||
| 742 | if (wacom->id[1] & 0x02) | ||
| 743 | input_sync(input); | ||
| 744 | } | ||
| 745 | idx = (wacom->id[1] & 0x02) - 1; | ||
| 746 | if (idx == 1) | ||
| 747 | wacom_tpc_touch_out(wacom, idx); | ||
| 748 | } else { | ||
| 749 | /* one finger touch */ | ||
| 750 | wacom_tpc_touch_out(wacom, 0); | 752 | wacom_tpc_touch_out(wacom, 0); |
| 751 | } | 753 | |
| 752 | wacom->id[0] = 0; | 754 | if (wacom->id[1] & 0x02) |
| 753 | } | 755 | wacom_tpc_touch_out(wacom, 1); |
| 754 | } else if (wacom->id[0]) { /* force touch out-prox */ | 756 | } else |
| 755 | wacom_tpc_touch_out(wacom, 0); | 757 | /* one finger touch */ |
| 758 | wacom_tpc_touch_out(wacom, 0); | ||
| 759 | |||
| 760 | wacom->id[0] = 0; | ||
| 756 | } | 761 | } |
| 757 | return 1; | 762 | /* keep prox bit to send proper out-prox event */ |
| 763 | wacom->id[1] = prox; | ||
| 758 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ | 764 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ |
| 759 | prox = data[1] & 0x20; | 765 | prox = data[1] & 0x20; |
| 760 | 766 | ||
| 761 | if (!wacom->id[0]) { /* first in prox */ | 767 | if (!wacom->shared->stylus_in_proximity) { /* first in prox */ |
| 762 | /* Going into proximity select tool */ | 768 | /* Going into proximity select tool */ |
| 763 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 769 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
| 764 | if (wacom->tool[0] == BTN_TOOL_PEN) | 770 | if (wacom->tool[0] == BTN_TOOL_PEN) |
| @@ -783,9 +789,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) | |||
| 783 | } | 789 | } |
| 784 | input_report_key(input, wacom->tool[0], prox); | 790 | input_report_key(input, wacom->tool[0], prox); |
| 785 | input_report_abs(input, ABS_MISC, wacom->id[0]); | 791 | input_report_abs(input, ABS_MISC, wacom->id[0]); |
| 786 | return 1; | 792 | retval = 1; |
| 787 | } | 793 | } |
| 788 | return 0; | 794 | return retval; |
| 789 | } | 795 | } |
| 790 | 796 | ||
| 791 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) | 797 | void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 69098a2aa690..063f1af3204f 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -80,9 +80,10 @@ struct wacom_shared { | |||
| 80 | struct wacom_wac { | 80 | struct wacom_wac { |
| 81 | char name[64]; | 81 | char name[64]; |
| 82 | unsigned char *data; | 82 | unsigned char *data; |
| 83 | int tool[2]; | 83 | int tool[3]; |
| 84 | int id[2]; | 84 | int id[3]; |
| 85 | __u32 serial[2]; | 85 | __u32 serial[2]; |
| 86 | int last_finger; | ||
| 86 | struct wacom_features features; | 87 | struct wacom_features features; |
| 87 | struct wacom_shared *shared; | 88 | struct wacom_shared *shared; |
| 88 | struct input_dev *input; | 89 | struct input_dev *input; |
