]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/class/usblp.c
USB: remove err() macro from usb class drivers
[linux-2.6-omap-h63xx.git] / drivers / usb / class / usblp.c
index 9a1478972bf5aee1cf75c5f70434d4e68c5fa83c..b5775af3ba26e4dc94db3b2ebb205abbfce4f2ea 100644 (file)
@@ -28,6 +28,7 @@
  *     v0.12 - add hpoj.sourceforge.net ioctls (David Paschal)
  *     v0.13 - alloc space for statusbuf (<status> not on stack);
  *             use usb_buffer_alloc() for read buf & write buf;
+ *      none  - Maintained in Linux kernel after v0.13
  */
 
 /*
@@ -69,7 +70,6 @@
 #define USBLP_DEVICE_ID_SIZE   1024
 
 /* ioctls: */
-#define LPGETSTATUS            0x060b          /* same as in drivers/char/lp.c */
 #define IOCNR_GET_DEVICE_ID            1
 #define IOCNR_GET_PROTOCOLS            2
 #define IOCNR_SET_PROTOCOL             3
@@ -115,7 +115,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H
 #define USBLP_MINORS           16
 #define USBLP_MINOR_BASE       0
 
-#define USBLP_WRITE_TIMEOUT    (5000)                  /* 5 seconds */
+#define USBLP_CTL_TIMEOUT      5000                    /* 5 seconds */
 
 #define USBLP_FIRST_PROTOCOL   1
 #define USBLP_LAST_PROTOCOL    3
@@ -159,10 +159,12 @@ struct usblp {
        int                     wstatus;        /* bytes written or error */
        int                     rstatus;        /* bytes ready or error */
        unsigned int            quirks;                 /* quirks flags */
+       unsigned int            flags;                  /* mode flags */
        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           no_paper;               /* Paper Out happened */
        unsigned char           *device_id_string;      /* IEEE 1284 DEVICE ID string (ptr) */
                                                        /* first 2 bytes are (big-endian) length */
 };
@@ -259,7 +261,7 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i
 
        retval = usb_control_msg(usblp->dev,
                dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
-               request, type | dir | recip, value, index, buf, len, USBLP_WRITE_TIMEOUT);
+               request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT);
        dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d",
                request, !!dir, recip, value, index, len, retval);
        return retval < 0 ? retval : 0;
@@ -289,16 +291,17 @@ static int proto_bias = -1;
 static void usblp_bulk_read(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
+       int status = urb->status;
 
        if (usblp->present && usblp->used) {
-               if (urb->status)
+               if (status)
                        printk(KERN_WARNING "usblp%d: "
                            "nonzero read bulk status received: %d\n",
-                           usblp->minor, urb->status);
+                           usblp->minor, status);
        }
        spin_lock(&usblp->lock);
-       if (urb->status < 0)
-               usblp->rstatus = urb->status;
+       if (status < 0)
+               usblp->rstatus = status;
        else
                usblp->rstatus = urb->actual_length;
        usblp->rcomplete = 1;
@@ -311,25 +314,24 @@ static void usblp_bulk_read(struct urb *urb)
 static void usblp_bulk_write(struct urb *urb)
 {
        struct usblp *usblp = urb->context;
+       int status = urb->status;
 
        if (usblp->present && usblp->used) {
-               if (urb->status)
+               if (status)
                        printk(KERN_WARNING "usblp%d: "
                            "nonzero write bulk status received: %d\n",
-                           usblp->minor, urb->status);
+                           usblp->minor, status);
        }
        spin_lock(&usblp->lock);
-       if (urb->status < 0)
-               usblp->wstatus = urb->status;
+       if (status < 0)
+               usblp->wstatus = status;
        else
                usblp->wstatus = urb->actual_length;
+       usblp->no_paper = 0;
        usblp->wcomplete = 1;
        wake_up(&usblp->wwait);
        spin_unlock(&usblp->lock);
 
-       /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */
-       kfree(urb->transfer_buffer);
-       urb->transfer_buffer = NULL;    /* Not refcounted, so to be safe... */
        usb_free_urb(urb);
 }
 
@@ -344,16 +346,17 @@ static int usblp_check_status(struct usblp *usblp, int err)
        unsigned char status, newerr = 0;
        int error;
 
-       error = usblp_read_status (usblp, usblp->statusbuf);
-       if (error < 0) {
+       mutex_lock(&usblp->mut);
+       if ((error = usblp_read_status(usblp, usblp->statusbuf)) < 0) {
+               mutex_unlock(&usblp->mut);
                if (printk_ratelimit())
                        printk(KERN_ERR
                                "usblp%d: error %d reading printer status\n",
                                usblp->minor, error);
                return 0;
        }
-
        status = *usblp->statusbuf;
+       mutex_unlock(&usblp->mut);
 
        if (~status & LP_PERRORP)
                newerr = 3;
@@ -409,18 +412,10 @@ static int usblp_open(struct inode *inode, struct file *file)
                goto out;
 
        /*
-        * TODO: need to implement LP_ABORTOPEN + O_NONBLOCK as in drivers/char/lp.c ???
-        * This is #if 0-ed because we *don't* want to fail an open
-        * just because the printer is off-line.
+        * We do not implement LP_ABORTOPEN/LPABORTOPEN for two reasons:
+        *  - We do not want persistent state which close(2) does not clear
+        *  - It is not used anyway, according to CUPS people
         */
-#if 0
-       if ((retval = usblp_check_status(usblp, 0))) {
-               retval = retval > 1 ? -EIO : -ENOSPC;
-               goto out;
-       }
-#else
-       retval = 0;
-#endif
 
        retval = usb_autopm_get_interface(intf);
        if (retval < 0)
@@ -433,6 +428,7 @@ static int usblp_open(struct inode *inode, struct file *file)
        usblp->rcomplete = 0;
 
        if (handle_bidir(usblp) < 0) {
+               usb_autopm_put_interface(intf);
                usblp->used = 0;
                file->private_data = NULL;
                retval = -EIO;
@@ -461,6 +457,8 @@ static int usblp_release(struct inode *inode, struct file *file)
 {
        struct usblp *usblp = file->private_data;
 
+       usblp->flags &= ~LP_ABORT;
+
        mutex_lock (&usblp_mutex);
        usblp->used = 0;
        if (usblp->present) {
@@ -483,8 +481,8 @@ static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait
        poll_wait(file, &usblp->rwait, wait);
        poll_wait(file, &usblp->wwait, wait);
        spin_lock_irqsave(&usblp->lock, flags);
-       ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN  | POLLRDNORM)
-                              | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM);
+       ret = ((usblp->bidir && usblp->rcomplete) ? POLLIN  | POLLRDNORM : 0) |
+          ((usblp->no_paper || usblp->wcomplete) ? POLLOUT | POLLWRNORM : 0);
        spin_unlock_irqrestore(&usblp->lock, flags);
        return ret;
 }
@@ -595,8 +593,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                err = usblp_hp_channel_change_request(usblp,
                                        arg, &newChannel);
                                if (err < 0) {
-                                       err("usblp%d: error = %d setting "
-                                               "HP channel",
+                                       dev_err(&usblp->dev->dev,
+                                               "usblp%d: error = %d setting "
+                                               "HP channel\n",
                                                usblp->minor, err);
                                        retval = -EIO;
                                        goto done;
@@ -673,6 +672,13 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                        retval = -EFAULT;
                                break;
 
+                       case LPABORT:
+                               if (arg)
+                                       usblp->flags |= LP_ABORT;
+                               else
+                                       usblp->flags &= ~LP_ABORT;
+                               break;
+
                        default:
                                retval = -ENOTTY;
                }
@@ -682,10 +688,30 @@ done:
        return retval;
 }
 
+static struct urb *usblp_new_writeurb(struct usblp *usblp, int transfer_length)
+{
+       struct urb *urb;
+       char *writebuf;
+
+       if ((writebuf = kmalloc(transfer_length, GFP_KERNEL)) == NULL)
+               return NULL;
+       if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) {
+               kfree(writebuf);
+               return NULL;
+       }
+
+       usb_fill_bulk_urb(urb, usblp->dev,
+               usb_sndbulkpipe(usblp->dev,
+                usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress),
+               writebuf, transfer_length, usblp_bulk_write, usblp);
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       return urb;
+}
+
 static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
        struct usblp *usblp = file->private_data;
-       char *writebuf;
        struct urb *writeurb;
        int rv;
        int transfer_length;
@@ -706,17 +732,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
                        transfer_length = USBLP_BUF_SIZE;
 
                rv = -ENOMEM;
-               if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL)
-                       goto raise_buf;
-               if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL)
+               if ((writeurb = usblp_new_writeurb(usblp, transfer_length)) == NULL)
                        goto raise_urb;
-               usb_fill_bulk_urb(writeurb, usblp->dev,
-                       usb_sndbulkpipe(usblp->dev,
-                         usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress),
-                       writebuf, transfer_length, usblp_bulk_write, usblp);
                usb_anchor_urb(writeurb, &usblp->urbs);
 
-               if (copy_from_user(writebuf,
+               if (copy_from_user(writeurb->transfer_buffer,
                                   buffer + writecount, transfer_length)) {
                        rv = -EFAULT;
                        goto raise_badaddr;
@@ -728,6 +748,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
                if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) {
                        usblp->wstatus = 0;
                        spin_lock_irq(&usblp->lock);
+                       usblp->no_paper = 0;
                        usblp->wcomplete = 1;
                        wake_up(&usblp->wwait);
                        spin_unlock_irq(&usblp->lock);
@@ -741,15 +762,21 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
                 */
                rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK));
                if (rv < 0) {
-                       /*
-                        * If interrupted, we simply leave the URB to dangle,
-                        * so the ->release will call usb_kill_urb().
-                        */
+                       if (rv == -EAGAIN) {
+                               /* Presume that it's going to complete well. */
+                               writecount += transfer_length;
+                       }
+                       if (rv == -ENOSPC) {
+                               spin_lock_irq(&usblp->lock);
+                               usblp->no_paper = 1;    /* Mark for poll(2) */
+                               spin_unlock_irq(&usblp->lock);
+                               writecount += transfer_length;
+                       }
+                       /* Leave URB dangling, to be cleaned on close. */
                        goto collect_error;
                }
 
                if (usblp->wstatus < 0) {
-                       usblp_check_status(usblp, 0);
                        rv = -EIO;
                        goto collect_error;
                }
@@ -768,8 +795,6 @@ raise_badaddr:
        usb_unanchor_urb(writeurb);
        usb_free_urb(writeurb);
 raise_urb:
-       kfree(writebuf);
-raise_buf:
 raise_wait:
 collect_error:         /* Out of raise sequence */
        mutex_unlock(&usblp->wmut);
@@ -835,32 +860,36 @@ done:
  * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use
  * select(2) or poll(2) to wait for the buffer to drain before closing.
  * Alternatively, set blocking mode with fcntl and issue a zero-size write.
- *
- * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot
- * to check the return code for timeout expiration, so it had no effect.
- * Apparently, it was intended to check for error conditons, such as out
- * of paper. It is going to return when we settle things with CUPS. XXX
  */
 static int usblp_wwait(struct usblp *usblp, int nonblock)
 {
        DECLARE_WAITQUEUE(waita, current);
        int rc;
+       int err = 0;
 
        add_wait_queue(&usblp->wwait, &waita);
        for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
                if (mutex_lock_interruptible(&usblp->mut)) {
                        rc = -EINTR;
                        break;
                }
-               set_current_state(TASK_INTERRUPTIBLE);
-               if ((rc = usblp_wtest(usblp, nonblock)) < 0) {
-                       mutex_unlock(&usblp->mut);
-                       break;
-               }
+               rc = usblp_wtest(usblp, nonblock);
                mutex_unlock(&usblp->mut);
-               if (rc == 0)
+               if (rc <= 0)
                        break;
-               schedule();
+
+               if (usblp->flags & LP_ABORT) {
+                       if (schedule_timeout(msecs_to_jiffies(5000)) == 0) {
+                               err = usblp_check_status(usblp, err);
+                               if (err == 1) { /* Paper out */
+                                       rc = -ENOSPC;
+                                       break;
+                               }
+                       }
+               } else {
+                       schedule();
+               }
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&usblp->wwait, &waita);
@@ -1048,15 +1077,16 @@ static int usblp_probe(struct usb_interface *intf,
                       const struct usb_device_id *id)
 {
        struct usb_device *dev = interface_to_usbdev (intf);
-       struct usblp *usblp = NULL;
+       struct usblp *usblp;
        int protocol;
        int retval;
 
        /* Malloc and start initializing usblp structure so we can use it
         * directly. */
-       if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) {
+       usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL);
+       if (!usblp) {
                retval = -ENOMEM;
-               goto abort;
+               goto abort_ret;
        }
        usblp->dev = dev;
        mutex_init(&usblp->wmut);
@@ -1151,12 +1181,11 @@ abort_intfdata:
        usb_set_intfdata (intf, NULL);
        device_remove_file(&intf->dev, &dev_attr_ieee1284_id);
 abort:
-       if (usblp) {
-               kfree(usblp->readbuf);
-               kfree(usblp->statusbuf);
-               kfree(usblp->device_id_string);
-               kfree(usblp);
-       }
+       kfree(usblp->readbuf);
+       kfree(usblp->statusbuf);
+       kfree(usblp->device_id_string);
+       kfree(usblp);
+abort_ret:
        return retval;
 }
 
@@ -1317,7 +1346,7 @@ static void usblp_disconnect(struct usb_interface *intf)
        usb_deregister_dev(intf, &usblp_class);
 
        if (!usblp || !usblp->dev) {
-               err("bogus disconnect");
+               dev_err(&intf->dev, "bogus disconnect\n");
                BUG ();
        }