aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPing Cheng <pingc@wacom.com>2010-03-20 01:18:15 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2010-04-14 02:24:06 -0400
commit4492efffffeb88d87e7aa74765f3c53b3a7dd40f (patch)
tree258b17da4faf0934efb8bc63a5163d77e047dbc8
parent3b57ca0f80c5c8994b5b1e3d3f904cfe727951f2 (diff)
Input: wacom - share pen info with touch of the same ID
Touch enbaled devices share the same product ID with pen. However, we do not want to post touch events while pen is in prox. To do so, we used to keep a local static variable to keep track of if pen is in prox or not. This works fine for Tablet PC devices since there is only one device attached. With the newer touch enabled regular tablets, we can not make this assumption any more, i.e, one system may have more than one identical tablet plugged in. This patch adds an new entry, shared, into the struct wacom_wac so touch data can access pen data to locally. This solution assumes the two tools (touch and pen) of the same ID will be probed one after the other without interruption in between by another Wacom device of the same ID.
-rw-r--r--drivers/input/tablet/wacom_sys.c83
-rw-r--r--drivers/input/tablet/wacom_wac.c33
-rw-r--r--drivers/input/tablet/wacom_wac.h5
3 files changed, 99 insertions, 22 deletions
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c
index f46502589e4e..a03ca219d49f 100644
--- a/drivers/input/tablet/wacom_sys.c
+++ b/drivers/input/tablet/wacom_sys.c
@@ -528,6 +528,81 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
528 return error; 528 return error;
529} 529}
530 530
531struct wacom_usbdev_data {
532 struct list_head list;
533 struct kref kref;
534 struct usb_device *dev;
535 struct wacom_shared shared;
536};
537
538static LIST_HEAD(wacom_udev_list);
539static DEFINE_MUTEX(wacom_udev_list_lock);
540
541static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
542{
543 struct wacom_usbdev_data *data;
544
545 list_for_each_entry(data, &wacom_udev_list, list) {
546 if (data->dev == dev) {
547 kref_get(&data->kref);
548 return data;
549 }
550 }
551
552 return NULL;
553}
554
555static int wacom_add_shared_data(struct wacom_wac *wacom,
556 struct usb_device *dev)
557{
558 struct wacom_usbdev_data *data;
559 int retval = 0;
560
561 mutex_lock(&wacom_udev_list_lock);
562
563 data = wacom_get_usbdev_data(dev);
564 if (!data) {
565 data = kzalloc(sizeof(struct wacom_usbdev_data), GFP_KERNEL);
566 if (!data) {
567 retval = -ENOMEM;
568 goto out;
569 }
570
571 kref_init(&data->kref);
572 data->dev = dev;
573 list_add_tail(&data->list, &wacom_udev_list);
574 }
575
576 wacom->shared = &data->shared;
577
578out:
579 mutex_unlock(&wacom_udev_list_lock);
580 return retval;
581}
582
583static void wacom_release_shared_data(struct kref *kref)
584{
585 struct wacom_usbdev_data *data =
586 container_of(kref, struct wacom_usbdev_data, kref);
587
588 mutex_lock(&wacom_udev_list_lock);
589 list_del(&data->list);
590 mutex_unlock(&wacom_udev_list_lock);
591
592 kfree(data);
593}
594
595static void wacom_remove_shared_data(struct wacom_wac *wacom)
596{
597 struct wacom_usbdev_data *data;
598
599 if (wacom->shared) {
600 data = container_of(wacom->shared, struct wacom_usbdev_data, shared);
601 kref_put(&data->kref, wacom_release_shared_data);
602 wacom->shared = NULL;
603 }
604}
605
531static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) 606static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id)
532{ 607{
533 struct usb_device *dev = interface_to_usbdev(intf); 608 struct usb_device *dev = interface_to_usbdev(intf);
@@ -600,6 +675,10 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
600 features->device_type == BTN_TOOL_PEN ? 675 features->device_type == BTN_TOOL_PEN ?
601 " Pen" : " Finger", 676 " Pen" : " Finger",
602 sizeof(wacom_wac->name)); 677 sizeof(wacom_wac->name));
678
679 error = wacom_add_shared_data(wacom_wac, dev);
680 if (error)
681 goto fail3;
603 } 682 }
604 683
605 input_dev->name = wacom_wac->name; 684 input_dev->name = wacom_wac->name;
@@ -624,7 +703,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
624 703
625 error = input_register_device(wacom->dev); 704 error = input_register_device(wacom->dev);
626 if (error) 705 if (error)
627 goto fail3; 706 goto fail4;
628 707
629 /* Note that if query fails it is not a hard failure */ 708 /* Note that if query fails it is not a hard failure */
630 wacom_query_tablet_data(intf, features); 709 wacom_query_tablet_data(intf, features);
@@ -632,6 +711,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
632 usb_set_intfdata(intf, wacom); 711 usb_set_intfdata(intf, wacom);
633 return 0; 712 return 0;
634 713
714 fail4: wacom_remove_shared_data(wacom_wac);
635 fail3: usb_free_urb(wacom->irq); 715 fail3: usb_free_urb(wacom->irq);
636 fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); 716 fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma);
637 fail1: input_free_device(input_dev); 717 fail1: input_free_device(input_dev);
@@ -651,6 +731,7 @@ static void wacom_disconnect(struct usb_interface *intf)
651 usb_free_urb(wacom->irq); 731 usb_free_urb(wacom->irq);
652 usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, 732 usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX,
653 wacom->wacom_wac->data, wacom->data_dma); 733 wacom->wacom_wac->data, wacom->data_dma);
734 wacom_remove_shared_data(wacom->wacom_wac);
654 kfree(wacom->wacom_wac); 735 kfree(wacom->wacom_wac);
655 kfree(wacom); 736 kfree(wacom);
656} 737}
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c
index b3ba3437a2eb..428144af865f 100644
--- a/drivers/input/tablet/wacom_wac.c
+++ b/drivers/input/tablet/wacom_wac.c
@@ -688,7 +688,6 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
688 struct wacom_features *features = &wacom->features; 688 struct wacom_features *features = &wacom->features;
689 char *data = wacom->data; 689 char *data = wacom->data;
690 int prox = 0, pressure, idx = -1; 690 int prox = 0, pressure, idx = -1;
691 static int stylusInProx, touchInProx = 1, touchOut;
692 struct urb *urb = ((struct wacom_combo *)wcombo)->urb; 691 struct urb *urb = ((struct wacom_combo *)wcombo)->urb;
693 692
694 dbg("wacom_tpc_irq: received report #%d", data[0]); 693 dbg("wacom_tpc_irq: received report #%d", data[0]);
@@ -707,16 +706,12 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
707 prox = data[1] & 0x03; 706 prox = data[1] & 0x03;
708 } 707 }
709 708
710 if (!stylusInProx) { /* stylus not in prox */ 709 if (!wacom->shared->stylus_in_proximity) {
711 if (prox) { 710 if (prox) {
712 if (touchInProx) { 711 wacom_tpc_touch_in(wacom, wcombo);
713 wacom_tpc_touch_in(wacom, wcombo);
714 touchOut = 1;
715 return 1;
716 }
717 } else { 712 } else {
718 /* 2FGT out-prox */
719 if (data[0] == WACOM_REPORT_TPC2FG) { 713 if (data[0] == WACOM_REPORT_TPC2FG) {
714 /* 2FGT out-prox */
720 idx = (wacom->id[1] & 0x01) - 1; 715 idx = (wacom->id[1] & 0x01) - 1;
721 if (idx == 0) { 716 if (idx == 0) {
722 wacom_tpc_touch_out(wacom, wcombo, idx); 717 wacom_tpc_touch_out(wacom, wcombo, idx);
@@ -727,23 +722,19 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
727 idx = (wacom->id[1] & 0x02) - 1; 722 idx = (wacom->id[1] & 0x02) - 1;
728 if (idx == 1) 723 if (idx == 1)
729 wacom_tpc_touch_out(wacom, wcombo, idx); 724 wacom_tpc_touch_out(wacom, wcombo, idx);
730 } else /* one finger touch */ 725 } else {
726 /* one finger touch */
731 wacom_tpc_touch_out(wacom, wcombo, 0); 727 wacom_tpc_touch_out(wacom, wcombo, 0);
732 touchOut = 0; 728 }
733 touchInProx = 1; 729 wacom->id[0] = 0;
734 return 1;
735 } 730 }
736 } else if (touchOut || !prox) { /* force touch out-prox */ 731 } else if (wacom->id[0]) { /* force touch out-prox */
737 wacom_tpc_touch_out(wacom, wcombo, 0); 732 wacom_tpc_touch_out(wacom, wcombo, 0);
738 touchOut = 0;
739 touchInProx = 1;
740 return 1;
741 } 733 }
734 return 1;
742 } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ 735 } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
743 prox = data[1] & 0x20; 736 prox = data[1] & 0x20;
744 737
745 touchInProx = 0;
746
747 if (!wacom->id[0]) { /* first in prox */ 738 if (!wacom->id[0]) { /* first in prox */
748 /* Going into proximity select tool */ 739 /* Going into proximity select tool */
749 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; 740 wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
@@ -751,6 +742,8 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
751 wacom->id[0] = STYLUS_DEVICE_ID; 742 wacom->id[0] = STYLUS_DEVICE_ID;
752 else 743 else
753 wacom->id[0] = ERASER_DEVICE_ID; 744 wacom->id[0] = ERASER_DEVICE_ID;
745
746 wacom->shared->stylus_in_proximity = true;
754 } 747 }
755 wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); 748 wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02);
756 wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); 749 wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10);
@@ -763,12 +756,10 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo)
763 wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); 756 wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05);
764 if (!prox) { /* out-prox */ 757 if (!prox) { /* out-prox */
765 wacom->id[0] = 0; 758 wacom->id[0] = 0;
766 /* pen is out so touch can be enabled now */ 759 wacom->shared->stylus_in_proximity = false;
767 touchInProx = 1;
768 } 760 }
769 wacom_report_key(wcombo, wacom->tool[0], prox); 761 wacom_report_key(wcombo, wacom->tool[0], prox);
770 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); 762 wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]);
771 stylusInProx = prox;
772 return 1; 763 return 1;
773 } 764 }
774 return 0; 765 return 0;
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h
index b50cf04e61a8..4b55fc7ad8ae 100644
--- a/drivers/input/tablet/wacom_wac.h
+++ b/drivers/input/tablet/wacom_wac.h
@@ -71,6 +71,10 @@ struct wacom_features {
71 unsigned char unitExpo; 71 unsigned char unitExpo;
72}; 72};
73 73
74struct wacom_shared {
75 bool stylus_in_proximity;
76};
77
74struct wacom_wac { 78struct wacom_wac {
75 char name[64]; 79 char name[64];
76 unsigned char *data; 80 unsigned char *data;
@@ -78,6 +82,7 @@ struct wacom_wac {
78 int id[2]; 82 int id[2];
79 __u32 serial[2]; 83 __u32 serial[2];
80 struct wacom_features features; 84 struct wacom_features features;
85 struct wacom_shared *shared;
81}; 86};
82 87
83#endif 88#endif