[PATCH] USB Storage: make OneTouch PM-aware

The OneTouch subdriver submits its own interrupt URB for notifications
about button presses.  Consequently it needs to know about suspend and
resume events, so it can cancel or restart the URB.

This patch (as593) adds a hook to struct us_data, to be used for
notifying subdrivers about Power Management events, and it implements
the hook in the OneTouch driver.

Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
Signed-off-by: Nick Sillik <[EMAIL PROTECTED]>
Signed-off-by: Matthew Dharm <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

---
commit 7931e1c6f8007d5fef8a0bb2dc71bd97315eeae9
tree aa4ace5efa3454324b10f0b4036fc87a3e815bcf
parent b9b09422570e5e35a9f590a1ead63e711aefac8c
author Matthew Dharm <[EMAIL PROTECTED]> Sun, 04 Dec 2005 21:56:51 -0800
committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Wed, 04 Jan 2006 13:51:41 -0800

 drivers/usb/storage/onetouch.c |   27 +++++++++++++++++++++++++++
 drivers/usb/storage/usb.c      |    4 ++++
 drivers/usb/storage/usb.h      |    9 ++++++++-
 3 files changed, 39 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index 89401a5..55ee2d3 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -52,6 +52,7 @@ 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)
@@ -89,6 +90,7 @@ static int usb_onetouch_open(struct inpu
 {
        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 +105,30 @@ static void usb_onetouch_close(struct in
        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;
@@ -185,6 +209,9 @@ int onetouch_connect_input(struct us_dat
 
        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);
 
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 356f471..ca02ae9 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -188,6 +188,8 @@ static int storage_suspend(struct usb_in
        down(&us->dev_semaphore);
 
        US_DEBUGP("%s\n", __FUNCTION__);
+       if (us->suspend_resume_hook)
+               (us->suspend_resume_hook)(us, US_SUSPEND);
        iface->dev.power.power_state.event = message.event;
 
        /* When runtime PM is working, we'll set a flag to indicate
@@ -204,6 +206,8 @@ static int storage_resume(struct usb_int
        down(&us->dev_semaphore);
 
        US_DEBUGP("%s\n", __FUNCTION__);
+       if (us->suspend_resume_hook)
+               (us->suspend_resume_hook)(us, US_RESUME);
        iface->dev.power.power_state.event = PM_EVENT_ON;
 
        up(&us->dev_semaphore);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 0cd1eeb..7259fd1 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -93,7 +93,11 @@ struct us_unusual_dev {
 typedef int (*trans_cmnd)(struct scsi_cmnd *, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
 typedef void (*proto_cmnd)(struct scsi_cmnd*, struct us_data*);
-typedef void (*extra_data_destructor)(void *);  /* extra data destructor   */
+typedef void (*extra_data_destructor)(void *); /* extra data destructor */
+typedef void (*pm_hook)(struct us_data *, int);        /* power management 
hook */
+
+#define US_SUSPEND     0
+#define US_RESUME      1
 
 /* we allocate one of these for every device that we remember */
 struct us_data {
@@ -149,6 +153,9 @@ struct us_data {
        /* subdriver information */
        void                    *extra;          /* Any extra data          */
        extra_data_destructor   extra_destructor;/* extra data destructor   */
+#ifdef CONFIG_PM
+       pm_hook                 suspend_resume_hook;
+#endif
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_idv37&alloc_id865&op=click
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to