Input: appletouch - implement reset-resume logic
authorOliver Neukum <oliver@neukum.org>
Tue, 17 Jun 2008 15:56:55 +0000 (11:56 -0400)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Tue, 17 Jun 2008 15:56:55 +0000 (11:56 -0400)
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>
drivers/input/mouse/appletouch.c
drivers/usb/core/quirks.c

index 8dd3942..ce6fdec 100644 (file)
@@ -589,6 +589,21 @@ static void atp_close(struct input_dev *input)
        dev->open = 0;
 }
 
+static int atp_handle_geyser(struct atp *dev)
+{
+       struct usb_device *udev = dev->udev;
+
+       if (!atp_is_fountain(dev)) {
+               /* switch to raw sensor mode */
+               if (atp_geyser_init(udev))
+                       return -EIO;
+
+               printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
+       }
+
+       return 0;
+}
+
 static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id)
 {
        struct atp *dev;
@@ -633,14 +648,6 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
        else
                dev->datalen = 81;
 
-       if (!atp_is_fountain(dev)) {
-               /* switch to raw sensor mode */
-               if (atp_geyser_init(udev))
-                       goto err_free_devs;
-
-               printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
-       }
-
        dev->urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!dev->urb)
                goto err_free_devs;
@@ -654,6 +661,10 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
                         usb_rcvintpipe(udev, int_in_endpointAddr),
                         dev->data, dev->datalen, atp_complete, dev, 1);
 
+       error = atp_handle_geyser(dev);
+       if (error)
+               goto err_free_buffer;
+
        usb_make_path(udev, dev->phys, sizeof(dev->phys));
        strlcat(dev->phys, "/input0", sizeof(dev->phys));
 
@@ -744,6 +755,20 @@ static void atp_disconnect(struct usb_interface *iface)
        printk(KERN_INFO "input: appletouch disconnected\n");
 }
 
+static int atp_recover(struct atp *dev)
+{
+       int error;
+
+       error = atp_handle_geyser(dev);
+       if (error)
+               return error;
+
+       if (dev->open && usb_submit_urb(dev->urb, GFP_ATOMIC))
+               return -EIO;
+
+       return 0;
+}
+
 static int atp_suspend(struct usb_interface *iface, pm_message_t message)
 {
        struct atp *dev = usb_get_intfdata(iface);
@@ -764,12 +789,20 @@ static int atp_resume(struct usb_interface *iface)
        return 0;
 }
 
+static int atp_reset_resume(struct usb_interface *iface)
+{
+       struct atp *dev = usb_get_intfdata(iface);
+
+       return atp_recover(dev);
+}
+
 static struct usb_driver atp_driver = {
        .name           = "appletouch",
        .probe          = atp_probe,
        .disconnect     = atp_disconnect,
        .suspend        = atp_suspend,
        .resume         = atp_resume,
+       .reset_resume   = atp_reset_resume,
        .id_table       = atp_table,
 };
 
index 2e20193..ec15f1d 100644 (file)
@@ -47,6 +47,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Edirol SD-20 */
        { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* appletouch */
+       { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* M-Systems Flash Disk Pioneers */
        { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },