|
@@ -390,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 */
|
|
@@ -417,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);
|
|
|
}
|
|
|
|
|
@@ -494,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)
|
|
|
{
|
|
@@ -522,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;
|
|
@@ -615,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(¤t_rx_req->list, &dev->rx_reqs);
|
|
|
spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
spin_unlock(&dev->lock_printer_io);
|
|
|
return -EAGAIN;
|
|
@@ -735,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;
|
|
@@ -791,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);
|
|
|
|
|
@@ -798,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);
|
|
@@ -1084,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);
|
|
|
}
|