aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet/wacom_wac.c
diff options
context:
space:
mode:
authorPing Cheng <pingc@wacom.com>2009-12-15 03:35:24 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-12-15 03:36:08 -0500
commitec67bbedcf290ef182a897017f65a2707106c7f8 (patch)
tree321fe650b72776e8555da3a94b049e2704bc2b2a /drivers/input/tablet/wacom_wac.c
parentee54500d7b960984df125bdd0cd2105d6150e8f1 (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.c204
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
611static 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
625static 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
638static 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
611static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) 699static 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};