aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input/tablet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/tablet')
-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