// SPDX-License-Identifier: GPL-2.0+/* * f_printer.c - USB printer function driver * * Copied from drivers/usb/gadget/legacy/printer.c, * which was: * * printer.c -- Printer gadget driver * * Copyright (C) 2003-2005 David Brownell * Copyright (C) 2006 Craig W. Nadler */ #include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/ioport.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/mutex.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/idr.h>#include <linux/timer.h>#include <linux/list.h>#include <linux/interrupt.h>#include <linux/device.h>#include <linux/moduleparam.h>#include <linux/fs.h>#include <linux/poll.h>#include <linux/types.h>#include <linux/ctype.h>#include <linux/cdev.h>#include <linux/kref.h> #include <asm/byteorder.h>#include <linux/io.h>#include <linux/irq.h>#include <linux/uaccess.h>#include <linux/unaligned.h> #include <linux/usb/ch9.h>#include <linux/usb/composite.h>#include <linux/usb/gadget.h>#include <linux/usb/g_printer.h> #include "u_printer.h" #define PRINTER_MINORS 4#define GET_DEVICE_ID 0#define GET_PORT_STATUS 1#define SOFT_RESET 2 #define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */ static int major, minors;static const struct class usb_gadget_class = { .name = "usb_printer_gadget",}; static DEFINE_IDA(printer_ida);static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */ /*-------------------------------------------------------------------------*/ struct printer_dev { spinlock_t lock; /* lock this structure */ /* lock buffer lists during read/write calls */ struct mutex lock_printer_io; struct usb_gadget *gadget; s8 interface; struct usb_ep *in_ep, *out_ep; struct kref kref; struct list_head rx_reqs; /* List of free RX structs */ struct list_head rx_reqs_active; /* List of Active RX xfers */ struct list_head rx_buffers; /* List of completed xfers */ /* wait until there is data to be read. */ wait_queue_head_t rx_wait; struct list_head tx_reqs; /* List of free TX structs */ struct list_head tx_reqs_active; /* List of Active TX xfers */ /* Wait until there are write buffers available to use. */ wait_queue_head_t tx_wait; /* Wait until all write buffers have been sent. */ wait_queue_head_t tx_flush_wait; struct usb_request *current_rx_req; size_t current_rx_bytes; u8 *current_rx_buf; u8 printer_status; u8 reset_printer; int minor; struct cdev printer_cdev; u8 printer_cdev_open; wait_queue_head_t wait; unsigned q_len; char **pnp_string; /* We don't own memory! */ struct usb_function function;}; static inline struct printer_dev *func_to_printer(struct usb_function *f){ return container_of(f, struct printer_dev, function);} /*-------------------------------------------------------------------------*/ /* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand. */ /* holds our biggest descriptor */#define USB_DESC_BUFSIZE 256#define USB_BUFSIZE 8192 static struct usb_interface_descriptor intf_desc = { .bLength = sizeof(intf_desc), .bDescriptorType = USB_DT_INTERFACE, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_PRINTER, .bInterfaceSubClass = 1, /* Printer Sub-Class */ .bInterfaceProtocol = 2, /* Bi-Directional */ .iInterface = 0}; static struct usb_endpoint_descriptor fs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK}; static struct usb_endpoint_descriptor fs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK}; static struct usb_descriptor_header *fs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &fs_ep_in_desc, (struct usb_descriptor_header *) &fs_ep_out_desc, NULL}; /* * usb 2.0 devices need to expose both high speed and full speed * descriptors, unless they only run at full speed. */ static struct usb_endpoint_descriptor hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512)}; static struct usb_endpoint_descriptor hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512)}; static struct usb_descriptor_header *hs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &hs_ep_in_desc, (struct usb_descriptor_header *) &hs_ep_out_desc, NULL}; /* * Added endpoint descriptors for 3.0 devices */ static struct usb_endpoint_descriptor ss_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024),}; static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = { .bLength = sizeof(ss_ep_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,}; static struct usb_endpoint_descriptor ss_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024),}; static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = { .bLength = sizeof(ss_ep_out_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,}; static struct usb_descriptor_header *ss_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &ss_ep_in_desc, (struct usb_descriptor_header *) &ss_ep_in_comp_desc, (struct usb_descriptor_header *) &ss_ep_out_desc, (struct usb_descriptor_header *) &ss_ep_out_comp_desc, NULL}; /* maxpacket and other transfer characteristics vary by speed. */static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, struct usb_endpoint_descriptor *fs, struct usb_endpoint_descriptor *hs, struct usb_endpoint_descriptor *ss){ switch (gadget->speed) { case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: return ss; case USB_SPEED_HIGH: return hs; default: return fs; }} /*-------------------------------------------------------------------------*/ static void printer_dev_free(struct kref *kref){ struct printer_dev *dev = container_of(kref, struct printer_dev, kref); kfree(dev);} static struct usb_request *printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags){ struct usb_request *req; req = usb_ep_alloc_request(ep, gfp_flags); if (req != NULL) { req->length = len; req->buf = kmalloc(len, gfp_flags); if (req->buf == NULL) { usb_ep_free_request(ep, req); return NULL; } } return req;} static voidprinter_req_free(struct usb_ep *ep, struct usb_request *req){ if (ep != NULL && req != NULL) { kfree(req->buf); usb_ep_free_request(ep, req); }} /*-------------------------------------------------------------------------*/ static void rx_complete(struct usb_ep *ep, struct usb_request *req){ struct printer_dev *dev = ep->driver_data; int status = req->status; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); list_del_init(&req->list); /* Remode from Active List */ switch (status) { /* normal completion */ case 0: 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 */ case -ECONNRESET: /* unlink */ case -ESHUTDOWN: /* disconnect etc */ VDBG(dev, "rx shutdown, code %d\n", status); list_add(&req->list, &dev->rx_reqs); break; /* for hardware automagic (such as pxa) */ case -ECONNABORTED: /* endpoint reset */ DBG(dev, "rx %s reset\n", ep->name); list_add(&req->list, &dev->rx_reqs); break; /* data overrun */ case -EOVERFLOW: fallthrough; default: DBG(dev, "rx status %d\n", status); list_add(&req->list, &dev->rx_reqs); break; } wake_up_interruptible(&dev->rx_wait); spin_unlock_irqrestore(&dev->lock, flags);} static void tx_complete(struct usb_ep *ep, struct usb_request *req){ struct printer_dev *dev = ep->driver_data; switch (req->status) { default: VDBG(dev, "tx err %d\n", req->status); fallthrough; case -ECONNRESET: /* unlink */ case -ESHUTDOWN: /* disconnect etc */ break; case 0: break; } spin_lock(&dev->lock); /* Take the request struct off the active list and put it on the * free list. */ list_del_init(&req->list); list_add(&req->list, &dev->tx_reqs); wake_up_interruptible(&dev->tx_wait); if (likely(list_empty(&dev->tx_reqs_active))) wake_up_interruptible(&dev->tx_flush_wait); spin_unlock(&dev->lock);} /*-------------------------------------------------------------------------*/ static intprinter_open(struct inode *inode, struct file *fd){ struct printer_dev *dev; unsigned long flags; int ret = -EBUSY; dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) { spin_unlock_irqrestore(&dev->lock, flags); return -ENODEV; } if (!dev->printer_cdev_open) { dev->printer_cdev_open = 1; fd->private_data = dev; ret = 0; /* Change the printer status to show that it's on-line. */ dev->printer_status |= PRINTER_SELECTED; kref_get(&dev->kref); } spin_unlock_irqrestore(&dev->lock, flags); return ret;} static intprinter_close(struct inode *inode, struct file *fd){ struct printer_dev *dev = fd->private_data; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); dev->printer_cdev_open = 0; fd->private_data = NULL; /* Change printer status to show that the printer is off-line. */ dev->printer_status &= ~PRINTER_SELECTED; spin_unlock_irqrestore(&dev->lock, flags); kref_put(&dev->kref, printer_dev_free); return 0;} /* This function must be called with interrupts turned off. */static voidsetup_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; /* here, we unlock, and only unlock, to avoid deadlock. */ spin_unlock(&dev->lock); error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC); spin_lock(&dev->lock); if (error) { DBG(dev, "rx submit --> %d\n", error); list_add(&req->list, &dev->rx_reqs); break; } /* if the req is empty, then add it into dev->rx_reqs_active. */ else if (list_empty(&req->list)) list_add(&req->list, &dev->rx_reqs_active); }} static ssize_tprinter_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr){ struct printer_dev *dev = fd->private_data; unsigned long flags; size_t size, not_copied, copied; size_t bytes_copied; struct usb_request *req; /* This is a pointer to the current USB rx request. */ struct usb_request *current_rx_req; /* This is the number of bytes in the current rx buffer. */ size_t current_rx_bytes; /* This is a pointer to the current rx buffer. */ u8 *current_rx_buf; if (len == 0) return -EINVAL; DBG(dev, "printer_read trying to read %d bytes\n", (int)len); mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) goto out_disabled; /* We will use this flag later to check if a printer reset happened * after we turn interrupts back on. */ dev->reset_printer = 0; setup_rx_reqs(dev); /* this dropped the lock - need to retest */ if (dev->interface < 0) goto out_disabled; bytes_copied = 0; current_rx_req = dev->current_rx_req; current_rx_bytes = dev->current_rx_bytes; current_rx_buf = dev->current_rx_buf; dev->current_rx_req = NULL; dev->current_rx_bytes = 0; dev->current_rx_buf = NULL; /* Check if there is any data in the read buffers. Please note that * current_rx_bytes is the number of bytes in the current rx buffer. * If it is zero then check if there are any other rx_buffers that * are on the completed list. We are only out of data if all rx * buffers are empty. */ if ((current_rx_bytes == 0) && (likely(list_empty(&dev->rx_buffers)))) { /* Turn interrupts back on before sleeping. */ spin_unlock_irqrestore(&dev->lock, flags); /* * If no data is available check if this is a NON-Blocking * call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } /* Sleep until data is available */ wait_event_interruptible(dev->rx_wait, (likely(!list_empty(&dev->rx_buffers)))); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) goto out_disabled; } Lines 1–500 of 1575. Load more
// SPDX-License-Identifier: GPL-2.0+ /* * f_printer.c - USB printer function driver * * Copied from drivers/usb/gadget/legacy/printer.c, * which was: * * printer.c -- Printer gadget driver * * Copyright (C) 2003-2005 David Brownell * Copyright (C) 2006 Craig W. Nadler */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ioport.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/idr.h> #include <linux/timer.h> #include <linux/list.h> #include <linux/interrupt.h> #include <linux/device.h> #include <linux/moduleparam.h> #include <linux/fs.h> #include <linux/poll.h> #include <linux/types.h> #include <linux/ctype.h> #include <linux/cdev.h> #include <linux/kref.h> #include <asm/byteorder.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/uaccess.h> #include <linux/unaligned.h> #include <linux/usb/ch9.h> #include <linux/usb/composite.h> #include <linux/usb/gadget.h> #include <linux/usb/g_printer.h> #include "u_printer.h" #define PRINTER_MINORS 4 #define GET_DEVICE_ID 0 #define GET_PORT_STATUS 1 #define SOFT_RESET 2 #define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */ static int major, minors; static const struct class usb_gadget_class = { .name = "usb_printer_gadget", }; static DEFINE_IDA(printer_ida); static DEFINE_MUTEX(printer_ida_lock); /* protects access do printer_ida */ /*-------------------------------------------------------------------------*/ struct printer_dev { spinlock_t lock; /* lock this structure */ /* lock buffer lists during read/write calls */ struct mutex lock_printer_io; struct usb_gadget *gadget; s8 interface; struct usb_ep *in_ep, *out_ep; struct kref kref; struct list_head rx_reqs; /* List of free RX structs */ struct list_head rx_reqs_active; /* List of Active RX xfers */ struct list_head rx_buffers; /* List of completed xfers */ /* wait until there is data to be read. */ wait_queue_head_t rx_wait; struct list_head tx_reqs; /* List of free TX structs */ struct list_head tx_reqs_active; /* List of Active TX xfers */ /* Wait until there are write buffers available to use. */ wait_queue_head_t tx_wait; /* Wait until all write buffers have been sent. */ wait_queue_head_t tx_flush_wait; struct usb_request *current_rx_req; size_t current_rx_bytes; u8 *current_rx_buf; u8 printer_status; u8 reset_printer; int minor; struct cdev printer_cdev; u8 printer_cdev_open; wait_queue_head_t wait; unsigned q_len; char **pnp_string; /* We don't own memory! */ struct usb_function function; }; static inline struct printer_dev *func_to_printer(struct usb_function *f) { return container_of(f, struct printer_dev, function); } /*-------------------------------------------------------------------------*/ /* * DESCRIPTORS ... most are static, but strings and (full) configuration * descriptors are built on demand. */ /* holds our biggest descriptor */ #define USB_DESC_BUFSIZE 256 #define USB_BUFSIZE 8192 static struct usb_interface_descriptor intf_desc = { .bLength = sizeof(intf_desc), .bDescriptorType = USB_DT_INTERFACE, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_PRINTER, .bInterfaceSubClass = 1, /* Printer Sub-Class */ .bInterfaceProtocol = 2, /* Bi-Directional */ .iInterface = 0 }; static struct usb_endpoint_descriptor fs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK }; static struct usb_endpoint_descriptor fs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK }; static struct usb_descriptor_header *fs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &fs_ep_in_desc, (struct usb_descriptor_header *) &fs_ep_out_desc, NULL }; /* * usb 2.0 devices need to expose both high speed and full speed * descriptors, unless they only run at full speed. */ static struct usb_endpoint_descriptor hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_endpoint_descriptor hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_descriptor_header *hs_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &hs_ep_in_desc, (struct usb_descriptor_header *) &hs_ep_out_desc, NULL }; /* * Added endpoint descriptors for 3.0 devices */ static struct usb_endpoint_descriptor ss_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = { .bLength = sizeof(ss_ep_in_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, }; static struct usb_endpoint_descriptor ss_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = cpu_to_le16(1024), }; static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = { .bLength = sizeof(ss_ep_out_comp_desc), .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, }; static struct usb_descriptor_header *ss_printer_function[] = { (struct usb_descriptor_header *) &intf_desc, (struct usb_descriptor_header *) &ss_ep_in_desc, (struct usb_descriptor_header *) &ss_ep_in_comp_desc, (struct usb_descriptor_header *) &ss_ep_out_desc, (struct usb_descriptor_header *) &ss_ep_out_comp_desc, NULL }; /* maxpacket and other transfer characteristics vary by speed. */ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, struct usb_endpoint_descriptor *fs, struct usb_endpoint_descriptor *hs, struct usb_endpoint_descriptor *ss) { switch (gadget->speed) { case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: return ss; case USB_SPEED_HIGH: return hs; default: return fs; } } /*-------------------------------------------------------------------------*/ static void printer_dev_free(struct kref *kref) { struct printer_dev *dev = container_of(kref, struct printer_dev, kref); kfree(dev); } static struct usb_request * printer_req_alloc(struct usb_ep *ep, unsigned len, gfp_t gfp_flags) { struct usb_request *req; req = usb_ep_alloc_request(ep, gfp_flags); if (req != NULL) { req->length = len; req->buf = kmalloc(len, gfp_flags); if (req->buf == NULL) { usb_ep_free_request(ep, req); return NULL; } } return req; } static void printer_req_free(struct usb_ep *ep, struct usb_request *req) { if (ep != NULL && req != NULL) { kfree(req->buf); usb_ep_free_request(ep, req); } } /*-------------------------------------------------------------------------*/ static void rx_complete(struct usb_ep *ep, struct usb_request *req) { struct printer_dev *dev = ep->driver_data; int status = req->status; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); list_del_init(&req->list); /* Remode from Active List */ switch (status) { /* normal completion */ case 0: 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 */ case -ECONNRESET: /* unlink */ case -ESHUTDOWN: /* disconnect etc */ VDBG(dev, "rx shutdown, code %d\n", status); list_add(&req->list, &dev->rx_reqs); break; /* for hardware automagic (such as pxa) */ case -ECONNABORTED: /* endpoint reset */ DBG(dev, "rx %s reset\n", ep->name); list_add(&req->list, &dev->rx_reqs); break; /* data overrun */ case -EOVERFLOW: fallthrough; default: DBG(dev, "rx status %d\n", status); list_add(&req->list, &dev->rx_reqs); break; } wake_up_interruptible(&dev->rx_wait); spin_unlock_irqrestore(&dev->lock, flags); } static void tx_complete(struct usb_ep *ep, struct usb_request *req) { struct printer_dev *dev = ep->driver_data; switch (req->status) { default: VDBG(dev, "tx err %d\n", req->status); fallthrough; case -ECONNRESET: /* unlink */ case -ESHUTDOWN: /* disconnect etc */ break; case 0: break; } spin_lock(&dev->lock); /* Take the request struct off the active list and put it on the * free list. */ list_del_init(&req->list); list_add(&req->list, &dev->tx_reqs); wake_up_interruptible(&dev->tx_wait); if (likely(list_empty(&dev->tx_reqs_active))) wake_up_interruptible(&dev->tx_flush_wait); spin_unlock(&dev->lock); } /*-------------------------------------------------------------------------*/ static int printer_open(struct inode *inode, struct file *fd) { struct printer_dev *dev; unsigned long flags; int ret = -EBUSY; dev = container_of(inode->i_cdev, struct printer_dev, printer_cdev); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) { spin_unlock_irqrestore(&dev->lock, flags); return -ENODEV; } if (!dev->printer_cdev_open) { dev->printer_cdev_open = 1; fd->private_data = dev; ret = 0; /* Change the printer status to show that it's on-line. */ dev->printer_status |= PRINTER_SELECTED; kref_get(&dev->kref); } spin_unlock_irqrestore(&dev->lock, flags); return ret; } static int printer_close(struct inode *inode, struct file *fd) { struct printer_dev *dev = fd->private_data; unsigned long flags; spin_lock_irqsave(&dev->lock, flags); dev->printer_cdev_open = 0; fd->private_data = NULL; /* Change printer status to show that the printer is off-line. */ dev->printer_status &= ~PRINTER_SELECTED; spin_unlock_irqrestore(&dev->lock, flags); kref_put(&dev->kref, printer_dev_free); 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; /* here, we unlock, and only unlock, to avoid deadlock. */ spin_unlock(&dev->lock); error = usb_ep_queue(dev->out_ep, req, GFP_ATOMIC); spin_lock(&dev->lock); if (error) { DBG(dev, "rx submit --> %d\n", error); list_add(&req->list, &dev->rx_reqs); break; } /* if the req is empty, then add it into dev->rx_reqs_active. */ else if (list_empty(&req->list)) 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) { struct printer_dev *dev = fd->private_data; unsigned long flags; size_t size, not_copied, copied; size_t bytes_copied; struct usb_request *req; /* This is a pointer to the current USB rx request. */ struct usb_request *current_rx_req; /* This is the number of bytes in the current rx buffer. */ size_t current_rx_bytes; /* This is a pointer to the current rx buffer. */ u8 *current_rx_buf; if (len == 0) return -EINVAL; DBG(dev, "printer_read trying to read %d bytes\n", (int)len); mutex_lock(&dev->lock_printer_io); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) goto out_disabled; /* We will use this flag later to check if a printer reset happened * after we turn interrupts back on. */ dev->reset_printer = 0; setup_rx_reqs(dev); /* this dropped the lock - need to retest */ if (dev->interface < 0) goto out_disabled; bytes_copied = 0; current_rx_req = dev->current_rx_req; current_rx_bytes = dev->current_rx_bytes; current_rx_buf = dev->current_rx_buf; dev->current_rx_req = NULL; dev->current_rx_bytes = 0; dev->current_rx_buf = NULL; /* Check if there is any data in the read buffers. Please note that * current_rx_bytes is the number of bytes in the current rx buffer. * If it is zero then check if there are any other rx_buffers that * are on the completed list. We are only out of data if all rx * buffers are empty. */ if ((current_rx_bytes == 0) && (likely(list_empty(&dev->rx_buffers)))) { /* Turn interrupts back on before sleeping. */ spin_unlock_irqrestore(&dev->lock, flags); /* * If no data is available check if this is a NON-Blocking * call or not. */ if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) { mutex_unlock(&dev->lock_printer_io); return -EAGAIN; } /* Sleep until data is available */ wait_event_interruptible(dev->rx_wait, (likely(!list_empty(&dev->rx_buffers)))); spin_lock_irqsave(&dev->lock, flags); if (dev->interface < 0) goto out_disabled; }