diff options
Diffstat (limited to 'drivers/input/tablet')
-rw-r--r-- | drivers/input/tablet/wacom_sys.c | 83 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.c | 33 | ||||
-rw-r--r-- | drivers/input/tablet/wacom_wac.h | 5 |
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 | ||
531 | struct wacom_usbdev_data { | ||
532 | struct list_head list; | ||
533 | struct kref kref; | ||
534 | struct usb_device *dev; | ||
535 | struct wacom_shared shared; | ||
536 | }; | ||
537 | |||
538 | static LIST_HEAD(wacom_udev_list); | ||
539 | static DEFINE_MUTEX(wacom_udev_list_lock); | ||
540 | |||
541 | static 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 | |||
555 | static 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 | |||
578 | out: | ||
579 | mutex_unlock(&wacom_udev_list_lock); | ||
580 | return retval; | ||
581 | } | ||
582 | |||
583 | static 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 | |||
595 | static 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 | |||
531 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 606 | static 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 | ||
74 | struct wacom_shared { | ||
75 | bool stylus_in_proximity; | ||
76 | }; | ||
77 | |||
74 | struct wacom_wac { | 78 | struct 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 |