Hi,

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.

        Regards
                Oliver

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>

--- current/drivers/usb/class/usblp.c	2006-09-20 05:42:06.000000000 +0200
+++ linux-2.6.18/drivers/usb/class/usblp.c	2006-10-05 08:50:57.000000000 +0200
@@ -154,6 +154,7 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 			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 @@
 		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);
@@ -1170,6 +1196,41 @@
 	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) },
@@ -1186,6 +1247,8 @@
 	.name =		"usblp",
 	.probe =	usblp_probe,
 	.disconnect =	usblp_disconnect,
+	.suspend =	usblp_suspend,
+	.resume =	usblp_resume,
 	.id_table =	usblp_ids,
 };
 
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys -- and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
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