]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/storage/onetouch.c
USB: fix use after free in wacom_sys.c
[linux-2.6-omap-h63xx.git] / drivers / usb / storage / onetouch.c
index 89401a59f95273cc904688098c9179d082e78658..3baf448e300d6125bee994de038baa2e0d70e9e2 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/input.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/module.h>
-#include <linux/usb.h>
 #include <linux/usb_ch9.h>
-#include <linux/usb_input.h>
+#include <linux/usb/input.h>
 #include "usb.h"
 #include "onetouch.h"
 #include "debug.h"
@@ -52,9 +50,10 @@ struct usb_onetouch {
        struct urb *irq;        /* urb for interrupt in report */
        unsigned char *data;    /* input data */
        dma_addr_t data_dma;
+       unsigned int is_open:1;
 };
 
-static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
+static void usb_onetouch_irq(struct urb *urb)
 {
        struct usb_onetouch *onetouch = urb->context;
        signed char *data = onetouch->data;
@@ -73,7 +72,6 @@ static void usb_onetouch_irq(struct urb *urb, struct pt_regs *regs)
                goto resubmit;
        }
 
-       input_regs(dev, regs);
        input_report_key(dev, ONETOUCH_BUTTON, data[0] & 0x02);
        input_sync(dev);
 
@@ -89,6 +87,7 @@ static int usb_onetouch_open(struct input_dev *dev)
 {
        struct usb_onetouch *onetouch = dev->private;
 
+       onetouch->is_open = 1;
        onetouch->irq->dev = onetouch->udev;
        if (usb_submit_urb(onetouch->irq, GFP_KERNEL)) {
                err("usb_submit_urb failed");
@@ -103,8 +102,30 @@ static void usb_onetouch_close(struct input_dev *dev)
        struct usb_onetouch *onetouch = dev->private;
 
        usb_kill_urb(onetouch->irq);
+       onetouch->is_open = 0;
 }
 
+#ifdef CONFIG_PM
+static void usb_onetouch_pm_hook(struct us_data *us, int action)
+{
+       struct usb_onetouch *onetouch = (struct usb_onetouch *) us->extra;
+
+       if (onetouch->is_open) {
+               switch (action) {
+               case US_SUSPEND:
+                       usb_kill_urb(onetouch->irq);
+                       break;
+               case US_RESUME:
+                       if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0)
+                               err("usb_submit_urb failed");
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+#endif /* CONFIG_PM */
+
 int onetouch_connect_input(struct us_data *ss)
 {
        struct usb_device *udev = ss->pusb_dev;
@@ -113,6 +134,7 @@ int onetouch_connect_input(struct us_data *ss)
        struct usb_onetouch *onetouch;
        struct input_dev *input_dev;
        int pipe, maxp;
+       int error = -ENOMEM;
 
        interface = ss->pusb_intf->cur_altsetting;
 
@@ -185,16 +207,22 @@ int onetouch_connect_input(struct us_data *ss)
 
        ss->extra_destructor = onetouch_release_input;
        ss->extra = onetouch;
+#ifdef CONFIG_PM
+       ss->suspend_resume_hook = usb_onetouch_pm_hook;
+#endif
 
-       input_register_device(onetouch->dev);
+       error = input_register_device(onetouch->dev);
+       if (error)
+               goto fail3;
 
        return 0;
 
+ fail3:        usb_free_urb(onetouch->irq);
  fail2:        usb_buffer_free(udev, ONETOUCH_PKT_LEN,
                        onetouch->data, onetouch->data_dma);
  fail1:        kfree(onetouch);
        input_free_device(input_dev);
-       return -ENOMEM;
+       return error;
 }
 
 void onetouch_release_input(void *onetouch_)