]> err.no Git - linux-2.6/blobdiff - drivers/usb/gadget/printer.c
usb: pxa27x_udc driver
[linux-2.6] / drivers / usb / gadget / printer.c
index 9fdabc8fcac43dbfdbed0dd45660d06fb1eed9c1..76be75e3ab8fe4a051240b8c37e7f15c8558edba 100644 (file)
@@ -92,7 +92,6 @@ struct printer_dev {
        u8                      *current_rx_buf;
        u8                      printer_status;
        u8                      reset_printer;
-       struct class_device     *printer_class_dev;
        struct cdev             printer_cdev;
        struct device           *pdev;
        u8                      printer_cdev_open;
@@ -391,9 +390,12 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
 
        /* normal completion */
        case 0:
-               list_add_tail(&req->list, &dev->rx_buffers);
-               wake_up_interruptible(&dev->rx_wait);
-               DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               if (req->actual > 0) {
+                       list_add_tail(&req->list, &dev->rx_buffers);
+                       DBG(dev, "G_Printer : rx length %d\n", req->actual);
+               } else {
+                       list_add(&req->list, &dev->rx_reqs);
+               }
                break;
 
        /* software-driven interface shutdown */
@@ -418,6 +420,8 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                list_add(&req->list, &dev->rx_reqs);
                break;
        }
+
+       wake_up_interruptible(&dev->rx_wait);
        spin_unlock_irqrestore(&dev->lock, flags);
 }
 
@@ -495,6 +499,39 @@ printer_close(struct inode *inode, struct file *fd)
        return 0;
 }
 
+/* This function must be called with interrupts turned off. */
+static void
+setup_rx_reqs(struct printer_dev *dev)
+{
+       struct usb_request              *req;
+
+       while (likely(!list_empty(&dev->rx_reqs))) {
+               int error;
+
+               req = container_of(dev->rx_reqs.next,
+                               struct usb_request, list);
+               list_del_init(&req->list);
+
+               /* The USB Host sends us whatever amount of data it wants to
+                * so we always set the length field to the full USB_BUFSIZE.
+                * If the amount of data is more than the read() caller asked
+                * for it will be stored in the request buffer until it is
+                * asked for by read().
+                */
+               req->length = USB_BUFSIZE;
+               req->complete = rx_complete;
+
+               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
+               if (error) {
+                       DBG(dev, "rx submit --> %d\n", error);
+                       list_add(&req->list, &dev->rx_reqs);
+                       break;
+               } else {
+                       list_add(&req->list, &dev->rx_reqs_active);
+               }
+       }
+}
+
 static ssize_t
 printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 {
@@ -523,31 +560,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
         */
        dev->reset_printer = 0;
 
-       while (likely(!list_empty(&dev->rx_reqs))) {
-               int error;
-
-               req = container_of(dev->rx_reqs.next,
-                               struct usb_request, list);
-               list_del_init(&req->list);
-
-               /* The USB Host sends us whatever amount of data it wants to
-                * so we always set the length field to the full USB_BUFSIZE.
-                * If the amount of data is more than the read() caller asked
-                * for it will be stored in the request buffer until it is
-                * asked for by read().
-                */
-               req->length = USB_BUFSIZE;
-               req->complete = rx_complete;
-
-               error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC);
-               if (error) {
-                       DBG(dev, "rx submit --> %d\n", error);
-                       list_add(&req->list, &dev->rx_reqs);
-                       break;
-               } else {
-                       list_add(&req->list, &dev->rx_reqs_active);
-               }
-       }
+       setup_rx_reqs(dev);
 
        bytes_copied = 0;
        current_rx_req = dev->current_rx_req;
@@ -616,9 +629,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
                spin_lock_irqsave(&dev->lock, flags);
 
-               /* We've disconnected or reset free the req and buffer */
+               /* We've disconnected or reset so return. */
                if (dev->reset_printer) {
-                       printer_req_free(dev->out_ep, current_rx_req);
+                       list_add(&current_rx_req->list, &dev->rx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -736,7 +749,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
                /* We've disconnected or reset so free the req and buffer */
                if (dev->reset_printer) {
-                       printer_req_free(dev->in_ep, req);
+                       list_add(&req->list, &dev->tx_reqs);
                        spin_unlock_irqrestore(&dev->lock, flags);
                        spin_unlock(&dev->lock_printer_io);
                        return -EAGAIN;
@@ -792,6 +805,12 @@ printer_poll(struct file *fd, poll_table *wait)
        unsigned long           flags;
        int                     status = 0;
 
+       spin_lock(&dev->lock_printer_io);
+       spin_lock_irqsave(&dev->lock, flags);
+       setup_rx_reqs(dev);
+       spin_unlock_irqrestore(&dev->lock, flags);
+       spin_unlock(&dev->lock_printer_io);
+
        poll_wait(fd, &dev->rx_wait, wait);
        poll_wait(fd, &dev->tx_wait, wait);
 
@@ -799,7 +818,8 @@ printer_poll(struct file *fd, poll_table *wait)
        if (likely(!list_empty(&dev->tx_reqs)))
                status |= POLLOUT | POLLWRNORM;
 
-       if (likely(!list_empty(&dev->rx_buffers)))
+       if (likely(dev->current_rx_bytes) ||
+                       likely(!list_empty(&dev->rx_buffers)))
                status |= POLLIN | POLLRDNORM;
 
        spin_unlock_irqrestore(&dev->lock, flags);
@@ -895,7 +915,7 @@ static void printer_reset_interface(struct printer_dev *dev)
        if (dev->interface < 0)
                return;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        if (dev->in)
                usb_ep_disable(dev->in_ep);
@@ -1085,6 +1105,7 @@ static void printer_soft_reset(struct printer_dev *dev)
        if (usb_ep_enable(dev->out_ep, dev->out))
                DBG(dev, "Failed to enable USB out_ep\n");
 
+       wake_up_interruptible(&dev->rx_wait);
        wake_up_interruptible(&dev->tx_wait);
        wake_up_interruptible(&dev->tx_flush_wait);
 }
@@ -1263,7 +1284,7 @@ printer_disconnect(struct usb_gadget *gadget)
        struct printer_dev      *dev = get_gadget_data(gadget);
        unsigned long           flags;
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        spin_lock_irqsave(&dev->lock, flags);
 
@@ -1279,7 +1300,7 @@ printer_unbind(struct usb_gadget *gadget)
        struct usb_request      *req;
 
 
-       DBG(dev, "%s\n", __FUNCTION__);
+       DBG(dev, "%s\n", __func__);
 
        /* Remove sysfs files */
        device_destroy(usb_gadget_class, g_printer_devno);
@@ -1299,7 +1320,7 @@ printer_unbind(struct usb_gadget *gadget)
                printer_req_free(dev->in_ep, req);
        }
 
-       if (dev->current_rx_req != NULL);
+       if (dev->current_rx_req != NULL)
                printer_req_free(dev->out_ep, dev->current_rx_req);
 
        while (!list_empty(&dev->rx_reqs)) {