From: Oliver Neukum <[EMAIL PROTECTED]>

this implements suspend support for usblp. According to the CUPS people
ENODEV will make CUPS retry the job. Thus it is returned in the runtime
case. My printer survives suspend/resume cycles with it.

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>
Signed-off-by: Vojtech Pavlik <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/class/usblp.c |   79 ++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index a161d70..809d465 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -154,6 +154,7 @@ struct usblp {
        unsigned char           used;                   /* True if open */
        unsigned char           present;                /* True if not 
disconnected */
        unsigned char           bidir;                  /* interface is 
bidirectional */
+       unsigned char           sleeping;               /* interface is 
suspended */
        unsigned char           *device_id_string;      /* IEEE 1284 DEVICE ID 
string (ptr) */
                                                        /* first 2 bytes are 
(big-endian) length */
 };
@@ -183,6 +184,7 @@ static void usblp_dump(struct usblp *usb
        dbg("quirks=%d", usblp->quirks);
        dbg("used=%d", usblp->used);
        dbg("bidir=%d", usblp->bidir);
+       dbg("sleeping=%d", usblp->sleeping);
        dbg("device_id_string=\"%s\"",
                usblp->device_id_string ?
                        usblp->device_id_string + 2 :
@@ -338,6 +340,20 @@ static int usblp_check_status(struct usb
        return newerr;
 }
 
+static int handle_bidir (struct usblp *usblp)
+{
+       if (usblp->bidir && usblp->used && !usblp->sleeping) {
+               usblp->readcount = 0;
+               usblp->readurb->dev = usblp->dev;
+               if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
+                       usblp->used = 0;
+                       return -EIO;
+               }
+       }
+
+       return 0;
+}
+
 /*
  * File op functions.
  */
@@ -390,14 +406,9 @@ #endif
        usblp->writeurb->status = 0;
        usblp->readurb->status = 0;
 
-       if (usblp->bidir) {
-               usblp->readcount = 0;
-               usblp->readurb->dev = usblp->dev;
-               if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
-                       retval = -EIO;
-                       usblp->used = 0;
-                       file->private_data = NULL;
-               }
+       if (handle_bidir(usblp) < 0) {
+               file->private_data = NULL;
+               retval = -EIO;
        }
 out:
        mutex_unlock (&usblp_mutex);
@@ -460,6 +471,11 @@ static long usblp_ioctl(struct file *fil
                goto done;
        }
 
+       if (usblp->sleeping) {
+               retval = -ENODEV;
+               goto done;
+       }
+
        dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, 
_IOC_TYPE(cmd),
                _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
 
@@ -658,6 +674,11 @@ static ssize_t usblp_write(struct file *
                        return -ENODEV;
                }
 
+               if (usblp->sleeping) {
+                       up (&usblp->sem);
+                       return writecount ? writecount : -ENODEV;
+               }
+
                if (usblp->writeurb->status != 0) {
                        if (usblp->quirks & USBLP_QUIRK_BIDIR) {
                                if (!usblp->wcomplete)
@@ -749,6 +770,11 @@ static ssize_t usblp_read(struct file *f
                goto done;
        }
 
+       if (usblp->sleeping) {
+               count = -ENODEV;
+               goto done;
+       }
+
        if (usblp->readurb->status) {
                err("usblp%d: error %d reading from printer",
                        usblp->minor, usblp->readurb->status);
@@ -1167,6 +1193,41 @@ static void usblp_disconnect(struct usb_
        mutex_unlock (&usblp_mutex);
 }
 
+static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
+{
+       struct usblp *usblp = usb_get_intfdata (intf);
+
+       /* this races against normal access and open */
+       mutex_lock (&usblp_mutex);
+       down (&usblp->sem);
+       /* we take no more IO */
+       usblp->sleeping = 1;
+       /* we wait for anything printing */
+       wait_event (usblp->wait, usblp->wcomplete || !usblp->present);
+       usblp_unlink_urbs(usblp);
+       up (&usblp->sem);
+       mutex_unlock (&usblp_mutex);
+
+       return 0;
+}
+
+static int usblp_resume (struct usb_interface *intf)
+{
+       struct usblp *usblp = usb_get_intfdata (intf);
+       int r;
+
+       mutex_lock (&usblp_mutex);
+       down (&usblp->sem);
+
+       usblp->sleeping = 0;
+       r = handle_bidir (usblp);
+
+       up (&usblp->sem);
+       mutex_unlock (&usblp_mutex);
+
+       return r;
+}
+
 static struct usb_device_id usblp_ids [] = {
        { USB_DEVICE_INFO(7, 1, 1) },
        { USB_DEVICE_INFO(7, 1, 2) },
@@ -1183,6 +1244,8 @@ static struct usb_driver usblp_driver = 
        .name =         "usblp",
        .probe =        usblp_probe,
        .disconnect =   usblp_disconnect,
+       .suspend =      usblp_suspend,
+       .resume =       usblp_resume,
        .id_table =     usblp_ids,
 };
 
-- 
1.4.2.4


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
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