diff options
| author | Oliver Neukum <oliver@neukum.org> | 2008-06-17 11:56:55 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2008-06-17 11:56:55 -0400 |
| commit | 90d95ef617a535a8832bdcb8dee07bf591e5dd82 (patch) | |
| tree | 5b1633d1c6384d0fc4f37e5cf9b86a53496f2597 | |
| parent | 2f6a77d56523c14651236bc401a99b0e2aca2fdd (diff) | |
Input: appletouch - implement reset-resume logic
On some boxes the touchpad needs to be reinitialized after resume to make
it function again. This fixes bugzilla #10825.
Signed-off-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
| -rw-r--r-- | drivers/input/mouse/appletouch.c | 49 | ||||
| -rw-r--r-- | drivers/usb/core/quirks.c | 3 |
2 files changed, 44 insertions, 8 deletions
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 8dd3942f3022..ce6fdec19e14 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
| @@ -589,6 +589,21 @@ static void atp_close(struct input_dev *input) | |||
| 589 | dev->open = 0; | 589 | dev->open = 0; |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | static int atp_handle_geyser(struct atp *dev) | ||
| 593 | { | ||
| 594 | struct usb_device *udev = dev->udev; | ||
| 595 | |||
| 596 | if (!atp_is_fountain(dev)) { | ||
| 597 | /* switch to raw sensor mode */ | ||
| 598 | if (atp_geyser_init(udev)) | ||
| 599 | return -EIO; | ||
| 600 | |||
| 601 | printk(KERN_INFO "appletouch: Geyser mode initialized.\n"); | ||
| 602 | } | ||
| 603 | |||
| 604 | return 0; | ||
| 605 | } | ||
| 606 | |||
| 592 | static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) | 607 | static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id) |
| 593 | { | 608 | { |
| 594 | struct atp *dev; | 609 | struct atp *dev; |
| @@ -633,14 +648,6 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
| 633 | else | 648 | else |
| 634 | dev->datalen = 81; | 649 | dev->datalen = 81; |
| 635 | 650 | ||
| 636 | if (!atp_is_fountain(dev)) { | ||
| 637 | /* switch to raw sensor mode */ | ||
| 638 | if (atp_geyser_init(udev)) | ||
| 639 | goto err_free_devs; | ||
| 640 | |||
| 641 | printk(KERN_INFO "appletouch: Geyser mode initialized.\n"); | ||
| 642 | } | ||
| 643 | |||
| 644 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); | 651 | dev->urb = usb_alloc_urb(0, GFP_KERNEL); |
| 645 | if (!dev->urb) | 652 | if (!dev->urb) |
| 646 | goto err_free_devs; | 653 | goto err_free_devs; |
| @@ -654,6 +661,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id | |||
| 654 | usb_rcvintpipe(udev, int_in_endpointAddr), | 661 | usb_rcvintpipe(udev, int_in_endpointAddr), |
| 655 | dev->data, dev->datalen, atp_complete, dev, 1); | 662 | dev->data, dev->datalen, atp_complete, dev, 1); |
| 656 | 663 | ||
| 664 | error = atp_handle_geyser(dev); | ||
| 665 | if (error) | ||
| 666 | goto err_free_buffer; | ||
| 667 | |||
| 657 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); | 668 | usb_make_path(udev, dev->phys, sizeof(dev->phys)); |
| 658 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); | 669 | strlcat(dev->phys, "/input0", sizeof(dev->phys)); |
| 659 | 670 | ||
| @@ -744,6 +755,20 @@ static void atp_disconnect(struct usb_interface *iface) | |||
| 744 | printk(KERN_INFO "input: appletouch disconnected\n"); | 755 | printk(KERN_INFO "input: appletouch disconnected\n"); |
| 745 | } | 756 | } |
| 746 | 757 | ||
| 758 | static int atp_recover(struct atp *dev) | ||
| 759 | { | ||
| 760 | int error; | ||
| 761 | |||
| 762 | error = atp_handle_geyser(dev); | ||
| 763 | if (error) | ||
| 764 | return error; | ||
| 765 | |||
| 766 | if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC)) | ||
| 767 | return -EIO; | ||
| 768 | |||
| 769 | return 0; | ||
| 770 | } | ||
| 771 | |||
| 747 | static int atp_suspend(struct usb_interface *iface, pm_message_t message) | 772 | static int atp_suspend(struct usb_interface *iface, pm_message_t message) |
| 748 | { | 773 | { |
| 749 | struct atp *dev = usb_get_intfdata(iface); | 774 | struct atp *dev = usb_get_intfdata(iface); |
| @@ -764,12 +789,20 @@ static int atp_resume(struct usb_interface *iface) | |||
| 764 | return 0; | 789 | return 0; |
| 765 | } | 790 | } |
| 766 | 791 | ||
| 792 | static int atp_reset_resume(struct usb_interface *iface) | ||
| 793 | { | ||
| 794 | struct atp *dev = usb_get_intfdata(iface); | ||
| 795 | |||
| 796 | return atp_recover(dev); | ||
| 797 | } | ||
| 798 | |||
| 767 | static struct usb_driver atp_driver = { | 799 | static struct usb_driver atp_driver = { |
| 768 | .name = "appletouch", | 800 | .name = "appletouch", |
| 769 | .probe = atp_probe, | 801 | .probe = atp_probe, |
| 770 | .disconnect = atp_disconnect, | 802 | .disconnect = atp_disconnect, |
| 771 | .suspend = atp_suspend, | 803 | .suspend = atp_suspend, |
| 772 | .resume = atp_resume, | 804 | .resume = atp_resume, |
| 805 | .reset_resume = atp_reset_resume, | ||
| 773 | .id_table = atp_table, | 806 | .id_table = atp_table, |
| 774 | }; | 807 | }; |
| 775 | 808 | ||
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 2e2019390290..ec15f1dd1d0b 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
| @@ -47,6 +47,9 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
| 47 | /* Edirol SD-20 */ | 47 | /* Edirol SD-20 */ |
| 48 | { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, | 48 | { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 49 | 49 | ||
| 50 | /* appletouch */ | ||
| 51 | { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
| 52 | |||
| 50 | /* M-Systems Flash Disk Pioneers */ | 53 | /* M-Systems Flash Disk Pioneers */ |
| 51 | { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, | 54 | { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, |
| 52 | 55 | ||
