/* 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 */
list_add(&req->list, &dev->rx_reqs);
break;
}
+
+ wake_up_interruptible(&dev->rx_wait);
spin_unlock_irqrestore(&dev->lock, flags);
}
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)
{
*/
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;
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(¤t_rx_req->list, &dev->rx_reqs);
spin_unlock_irqrestore(&dev->lock, flags);
spin_unlock(&dev->lock_printer_io);
return -EAGAIN;
/* 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;
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);
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);
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);
}