diff options
author | Ping Cheng <pingc@wacom.com> | 2009-12-15 03:35:24 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-12-15 03:36:08 -0500 |
commit | ec67bbedcf290ef182a897017f65a2707106c7f8 (patch) | |
tree | 321fe650b72776e8555da3a94b049e2704bc2b2a /drivers/input/tablet/wacom_wac.c | |
parent | ee54500d7b960984df125bdd0cd2105d6150e8f1 (diff) |
Input: wacom - add support for new LCD tablets
This adds support for the foolowing Wacom devices:
- 0x9F - a single touch only LCD tablet;
- 0xE2 - a two finger touch only LCD tablet;
- 0xE3 - a two finger touch, penabled LCD tablet.
Signed-off-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/tablet/wacom_wac.c')
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 204 |
1 files changed, 145 insertions, 59 deletions
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index d5fc97d36102..46725894ea62 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -65,9 +65,8 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | |||
65 | 65 | ||
66 | prox = data[1] & 0x40; | 66 | prox = data[1] & 0x40; |
67 | 67 | ||
68 | wacom->id[0] = ERASER_DEVICE_ID; | ||
69 | if (prox) { | 68 | if (prox) { |
70 | 69 | wacom->id[0] = ERASER_DEVICE_ID; | |
71 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 70 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
72 | if (wacom->features->pressure_max > 255) | 71 | if (wacom->features->pressure_max > 255) |
73 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | 72 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); |
@@ -608,54 +607,146 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
608 | return 1; | 607 | return 1; |
609 | } | 608 | } |
610 | 609 | ||
610 | |||
611 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) | ||
612 | { | ||
613 | wacom_report_abs(wcombo, ABS_X, | ||
614 | (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); | ||
615 | wacom_report_abs(wcombo, ABS_Y, | ||
616 | (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); | ||
617 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
618 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
619 | if (idx) | ||
620 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
621 | else | ||
622 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
623 | } | ||
624 | |||
625 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) | ||
626 | { | ||
627 | wacom_report_abs(wcombo, ABS_X, 0); | ||
628 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
629 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
630 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
631 | if (idx) | ||
632 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
633 | else | ||
634 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) | ||
639 | { | ||
640 | char *data = wacom->data; | ||
641 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | ||
642 | static int firstFinger = 0; | ||
643 | static int secondFinger = 0; | ||
644 | |||
645 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | ||
646 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
647 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | ||
648 | |||
649 | if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { | ||
650 | switch (data[0]) { | ||
651 | case 6: | ||
652 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
653 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
654 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
655 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
656 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
657 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
658 | break; | ||
659 | case 13: | ||
660 | /* keep this byte to send proper out-prox event */ | ||
661 | wacom->id[1] = data[1] & 0x03; | ||
662 | |||
663 | if (data[1] & 0x01) { | ||
664 | wacom_tpc_finger_in(wacom, wcombo, data, 0); | ||
665 | firstFinger = 1; | ||
666 | } else if (firstFinger) { | ||
667 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
668 | } | ||
669 | |||
670 | if (data[1] & 0x02) { | ||
671 | /* sync first finger data */ | ||
672 | if (firstFinger) | ||
673 | wacom_input_sync(wcombo); | ||
674 | |||
675 | wacom_tpc_finger_in(wacom, wcombo, data, 1); | ||
676 | secondFinger = 1; | ||
677 | } else if (secondFinger) { | ||
678 | /* sync first finger data */ | ||
679 | if (firstFinger) | ||
680 | wacom_input_sync(wcombo); | ||
681 | |||
682 | wacom_tpc_touch_out(wacom, wcombo, 1); | ||
683 | secondFinger = 0; | ||
684 | } | ||
685 | if (!(data[1] & 0x01)) | ||
686 | firstFinger = 0; | ||
687 | break; | ||
688 | } | ||
689 | } else { | ||
690 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
691 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
692 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
693 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
694 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
695 | } | ||
696 | return; | ||
697 | } | ||
698 | |||
611 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | 699 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) |
612 | { | 700 | { |
613 | char *data = wacom->data; | 701 | char *data = wacom->data; |
614 | int prox = 0, pressure; | 702 | int prox = 0, pressure, idx = -1; |
615 | static int stylusInProx, touchInProx = 1, touchOut; | 703 | static int stylusInProx, touchInProx = 1, touchOut; |
616 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 704 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; |
617 | 705 | ||
618 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 706 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
619 | 707 | ||
620 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG || data[0] == 6) { /* Touch data */ | 708 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG || |
709 | data[0] == 6 || /* single touch */ | ||
710 | data[0] == 13) { /* 2FG touch */ | ||
621 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ | 711 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ |
622 | prox = data[0] & 0x03; | 712 | prox = data[0] & 0x01; |
623 | } else { /* with capacity */ | 713 | } else { /* with capacity */ |
624 | prox = data[1] & 0x03; | 714 | if (data[0] == 6) |
715 | /* single touch */ | ||
716 | prox = data[1] & 0x01; | ||
717 | else | ||
718 | /* 2FG touch data */ | ||
719 | prox = data[1] & 0x03; | ||
625 | } | 720 | } |
626 | 721 | ||
627 | if (!stylusInProx) { /* stylus not in prox */ | 722 | if (!stylusInProx) { /* stylus not in prox */ |
628 | if (prox) { | 723 | if (prox) { |
629 | if (touchInProx) { | 724 | if (touchInProx) { |
630 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; | 725 | wacom_tpc_touch_in(wacom, wcombo); |
631 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
632 | if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { | ||
633 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
634 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
635 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
636 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
637 | } else { | ||
638 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
639 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
640 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
641 | } | ||
642 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
643 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | ||
644 | touchOut = 1; | 726 | touchOut = 1; |
645 | return 1; | 727 | return 1; |
646 | } | 728 | } |
647 | } else { | 729 | } else { |
648 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 730 | /* 2FGT out-prox */ |
649 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | 731 | if ((data[0] & 0xff) == 13) { |
650 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 732 | idx = (wacom->id[1] & 0x01) - 1; |
733 | if (idx == 0) { | ||
734 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
735 | /* sync first finger event */ | ||
736 | if (wacom->id[1] & 0x02) | ||
737 | wacom_input_sync(wcombo); | ||
738 | } | ||
739 | idx = (wacom->id[1] & 0x02) - 1; | ||
740 | if (idx == 1) | ||
741 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
742 | } else /* one finger touch */ | ||
743 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
651 | touchOut = 0; | 744 | touchOut = 0; |
652 | touchInProx = 1; | 745 | touchInProx = 1; |
653 | return 1; | 746 | return 1; |
654 | } | 747 | } |
655 | } else if (touchOut || !prox) { /* force touch out-prox */ | 748 | } else if (touchOut || !prox) { /* force touch out-prox */ |
656 | wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); | 749 | wacom_tpc_touch_out(wacom, wcombo, 0); |
657 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
658 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
659 | touchOut = 0; | 750 | touchOut = 0; |
660 | touchInProx = 1; | 751 | touchInProx = 1; |
661 | return 1; | 752 | return 1; |
@@ -665,38 +756,14 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
665 | 756 | ||
666 | touchInProx = 0; | 757 | touchInProx = 0; |
667 | 758 | ||
668 | wacom->id[0] = ERASER_DEVICE_ID; | ||
669 | |||
670 | /* | ||
671 | * if going from out of proximity into proximity select between the eraser | ||
672 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
673 | * pressed else choose pen. if not a proximity change from out to in, send | ||
674 | * an out of proximity for previous tool then a in for new tool. | ||
675 | */ | ||
676 | if (prox) { /* in prox */ | 759 | if (prox) { /* in prox */ |
677 | if (!wacom->tool[0]) { | 760 | if (!wacom->id[0]) { |
678 | /* Going into proximity select tool */ | 761 | /* Going into proximity select tool */ |
679 | wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | 762 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
680 | if (wacom->tool[1] == BTN_TOOL_PEN) | 763 | if (wacom->tool[0] == BTN_TOOL_PEN) |
681 | wacom->id[0] = STYLUS_DEVICE_ID; | 764 | wacom->id[0] = STYLUS_DEVICE_ID; |
682 | } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { | 765 | else |
683 | /* | 766 | wacom->id[0] = ERASER_DEVICE_ID; |
684 | * was entered with stylus2 pressed | ||
685 | * report out proximity for previous tool | ||
686 | */ | ||
687 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
688 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
689 | wacom_input_sync(wcombo); | ||
690 | |||
691 | /* set new tool */ | ||
692 | wacom->tool[1] = BTN_TOOL_PEN; | ||
693 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
694 | return 0; | ||
695 | } | ||
696 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
697 | /* Unknown tool selected default to pen tool */ | ||
698 | wacom->tool[1] = BTN_TOOL_PEN; | ||
699 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
700 | } | 767 | } |
701 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 768 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
702 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | 769 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); |
@@ -706,17 +773,21 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
706 | if (pressure < 0) | 773 | if (pressure < 0) |
707 | pressure = wacom->features->pressure_max + pressure + 1; | 774 | pressure = wacom->features->pressure_max + pressure + 1; |
708 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | 775 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); |
709 | wacom_report_key(wcombo, BTN_TOUCH, pressure); | 776 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); |
710 | } else { | 777 | } else { |
778 | wacom_report_abs(wcombo, ABS_X, 0); | ||
779 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
711 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 780 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); |
712 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 781 | wacom_report_key(wcombo, BTN_STYLUS, 0); |
713 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 782 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
714 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 783 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
784 | wacom->id[0] = 0; | ||
785 | /* pen is out so touch can be enabled now */ | ||
786 | touchInProx = 1; | ||
715 | } | 787 | } |
716 | wacom_report_key(wcombo, wacom->tool[1], prox); | 788 | wacom_report_key(wcombo, wacom->tool[0], prox); |
717 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 789 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); |
718 | stylusInProx = prox; | 790 | stylusInProx = prox; |
719 | wacom->tool[0] = prox; | ||
720 | return 1; | 791 | return 1; |
721 | } | 792 | } |
722 | return 0; | 793 | return 0; |
@@ -751,6 +822,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
751 | return wacom_intuos_irq(wacom_wac, wcombo); | 822 | return wacom_intuos_irq(wacom_wac, wcombo); |
752 | 823 | ||
753 | case TABLETPC: | 824 | case TABLETPC: |
825 | case TABLETPC2FG: | ||
754 | return wacom_tpc_irq(wacom_wac, wcombo); | 826 | return wacom_tpc_irq(wacom_wac, wcombo); |
755 | 827 | ||
756 | default: | 828 | default: |
@@ -791,9 +863,17 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
791 | input_dev_i4s(input_dev, wacom_wac); | 863 | input_dev_i4s(input_dev, wacom_wac); |
792 | input_dev_i(input_dev, wacom_wac); | 864 | input_dev_i(input_dev, wacom_wac); |
793 | break; | 865 | break; |
866 | case TABLETPC2FG: | ||
867 | input_dev_tpc2fg(input_dev, wacom_wac); | ||
868 | /* fall through */ | ||
869 | case TABLETPC: | ||
870 | input_dev_tpc(input_dev, wacom_wac); | ||
871 | if (wacom_wac->features->device_type != BTN_TOOL_PEN) | ||
872 | break; /* no need to process stylus stuff */ | ||
873 | |||
874 | /* fall through */ | ||
794 | case PL: | 875 | case PL: |
795 | case PTU: | 876 | case PTU: |
796 | case TABLETPC: | ||
797 | input_dev_pl(input_dev, wacom_wac); | 877 | input_dev_pl(input_dev, wacom_wac); |
798 | /* fall through */ | 878 | /* fall through */ |
799 | case PENPARTNER: | 879 | case PENPARTNER: |
@@ -863,6 +943,9 @@ static struct wacom_features wacom_features[] = { | |||
863 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, | 943 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
864 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, | 944 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
865 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, | 945 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }, |
946 | { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }, | ||
947 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, | ||
948 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }, | ||
866 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, | 949 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }, |
867 | { } | 950 | { } |
868 | }; | 951 | }; |
@@ -927,6 +1010,9 @@ static struct usb_device_id wacom_ids[] = { | |||
927 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, | 1010 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, |
928 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, | 1011 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, |
929 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, | 1012 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, |
1013 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9F) }, | ||
1014 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE2) }, | ||
1015 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xE3) }, | ||
930 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | 1016 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, |
931 | { } | 1017 | { } |
932 | }; | 1018 | }; |