aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/class/usblp.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index a161d70e1e42..809d465eb257 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -154,6 +154,7 @@ struct usblp {
154 unsigned char used; /* True if open */ 154 unsigned char used; /* True if open */
155 unsigned char present; /* True if not disconnected */ 155 unsigned char present; /* True if not disconnected */
156 unsigned char bidir; /* interface is bidirectional */ 156 unsigned char bidir; /* interface is bidirectional */
157 unsigned char sleeping; /* interface is suspended */
157 unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ 158 unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */
158 /* first 2 bytes are (big-endian) length */ 159 /* first 2 bytes are (big-endian) length */
159}; 160};
@@ -183,6 +184,7 @@ static void usblp_dump(struct usblp *usblp) {
183 dbg("quirks=%d", usblp->quirks); 184 dbg("quirks=%d", usblp->quirks);
184 dbg("used=%d", usblp->used); 185 dbg("used=%d", usblp->used);
185 dbg("bidir=%d", usblp->bidir); 186 dbg("bidir=%d", usblp->bidir);
187 dbg("sleeping=%d", usblp->sleeping);
186 dbg("device_id_string=\"%s\"", 188 dbg("device_id_string=\"%s\"",
187 usblp->device_id_string ? 189 usblp->device_id_string ?
188 usblp->device_id_string + 2 : 190 usblp->device_id_string + 2 :
@@ -338,6 +340,20 @@ static int usblp_check_status(struct usblp *usblp, int err)
338 return newerr; 340 return newerr;
339} 341}
340 342
343static int handle_bidir (struct usblp *usblp)
344{
345 if (usblp->bidir && usblp->used && !usblp->sleeping) {
346 usblp->readcount = 0;
347 usblp->readurb->dev = usblp->dev;
348 if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
349 usblp->used = 0;
350 return -EIO;
351 }
352 }
353
354 return 0;
355}
356
341/* 357/*
342 * File op functions. 358 * File op functions.
343 */ 359 */
@@ -390,14 +406,9 @@ static int usblp_open(struct inode *inode, struct file *file)
390 usblp->writeurb->status = 0; 406 usblp->writeurb->status = 0;
391 usblp->readurb->status = 0; 407 usblp->readurb->status = 0;
392 408
393 if (usblp->bidir) { 409 if (handle_bidir(usblp) < 0) {
394 usblp->readcount = 0; 410 file->private_data = NULL;
395 usblp->readurb->dev = usblp->dev; 411 retval = -EIO;
396 if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) {
397 retval = -EIO;
398 usblp->used = 0;
399 file->private_data = NULL;
400 }
401 } 412 }
402out: 413out:
403 mutex_unlock (&usblp_mutex); 414 mutex_unlock (&usblp_mutex);
@@ -460,6 +471,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
460 goto done; 471 goto done;
461 } 472 }
462 473
474 if (usblp->sleeping) {
475 retval = -ENODEV;
476 goto done;
477 }
478
463 dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), 479 dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
464 _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); 480 _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) );
465 481
@@ -658,6 +674,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
658 return -ENODEV; 674 return -ENODEV;
659 } 675 }
660 676
677 if (usblp->sleeping) {
678 up (&usblp->sem);
679 return writecount ? writecount : -ENODEV;
680 }
681
661 if (usblp->writeurb->status != 0) { 682 if (usblp->writeurb->status != 0) {
662 if (usblp->quirks & USBLP_QUIRK_BIDIR) { 683 if (usblp->quirks & USBLP_QUIRK_BIDIR) {
663 if (!usblp->wcomplete) 684 if (!usblp->wcomplete)
@@ -749,6 +770,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
749 goto done; 770 goto done;
750 } 771 }
751 772
773 if (usblp->sleeping) {
774 count = -ENODEV;
775 goto done;
776 }
777
752 if (usblp->readurb->status) { 778 if (usblp->readurb->status) {
753 err("usblp%d: error %d reading from printer", 779 err("usblp%d: error %d reading from printer",
754 usblp->minor, usblp->readurb->status); 780 usblp->minor, usblp->readurb->status);
@@ -1167,6 +1193,41 @@ static void usblp_disconnect(struct usb_interface *intf)
1167 mutex_unlock (&usblp_mutex); 1193 mutex_unlock (&usblp_mutex);
1168} 1194}
1169 1195
1196static int usblp_suspend (struct usb_interface *intf, pm_message_t message)
1197{
1198 struct usblp *usblp = usb_get_intfdata (intf);
1199
1200 /* this races against normal access and open */
1201 mutex_lock (&usblp_mutex);
1202 down (&usblp->sem);
1203 /* we take no more IO */
1204 usblp->sleeping = 1;
1205 /* we wait for anything printing */
1206 wait_event (usblp->wait, usblp->wcomplete || !usblp->present);
1207 usblp_unlink_urbs(usblp);
1208 up (&usblp->sem);
1209 mutex_unlock (&usblp_mutex);
1210
1211 return 0;
1212}
1213
1214static int usblp_resume (struct usb_interface *intf)
1215{
1216 struct usblp *usblp = usb_get_intfdata (intf);
1217 int r;
1218
1219 mutex_lock (&usblp_mutex);
1220 down (&usblp->sem);
1221
1222 usblp->sleeping = 0;
1223 r = handle_bidir (usblp);
1224
1225 up (&usblp->sem);
1226 mutex_unlock (&usblp_mutex);
1227
1228 return r;
1229}
1230
1170static struct usb_device_id usblp_ids [] = { 1231static struct usb_device_id usblp_ids [] = {
1171 { USB_DEVICE_INFO(7, 1, 1) }, 1232 { USB_DEVICE_INFO(7, 1, 1) },
1172 { USB_DEVICE_INFO(7, 1, 2) }, 1233 { USB_DEVICE_INFO(7, 1, 2) },
@@ -1183,6 +1244,8 @@ static struct usb_driver usblp_driver = {
1183 .name = "usblp", 1244 .name = "usblp",
1184 .probe = usblp_probe, 1245 .probe = usblp_probe,
1185 .disconnect = usblp_disconnect, 1246 .disconnect = usblp_disconnect,
1247 .suspend = usblp_suspend,
1248 .resume = usblp_resume,
1186 .id_table = usblp_ids, 1249 .id_table = usblp_ids,
1187}; 1250};
1188 1251