summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/function/f_printer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/function/f_printer.c')
-rw-r--r--drivers/usb/gadget/function/f_printer.c99
1 files changed, 55 insertions, 44 deletions
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index abec5c58f525..d295ade8fa67 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -37,7 +37,7 @@
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/uaccess.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
#include <linux/usb/ch9.h>
#include <linux/usb/composite.h>
@@ -54,7 +54,10 @@
#define DEFAULT_Q_LEN 10 /* same as legacy g_printer gadget */
static int major, minors;
-static struct class *usb_gadget_class;
+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 */
@@ -89,7 +92,7 @@ struct printer_dev {
u8 printer_cdev_open;
wait_queue_head_t wait;
unsigned q_len;
- char *pnp_string; /* We don't own memory! */
+ char **pnp_string; /* We don't own memory! */
struct usb_function function;
};
@@ -210,6 +213,7 @@ static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget,
struct usb_endpoint_descriptor *ss)
{
switch (gadget->speed) {
+ case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER:
return ss;
case USB_SPEED_HIGH:
@@ -364,7 +368,7 @@ printer_open(struct inode *inode, struct file *fd)
spin_unlock_irqrestore(&dev->lock, flags);
kref_get(&dev->kref);
- DBG(dev, "printer_open returned %x\n", ret);
+
return ret;
}
@@ -382,7 +386,6 @@ printer_close(struct inode *inode, struct file *fd)
spin_unlock_irqrestore(&dev->lock, flags);
kref_put(&dev->kref, printer_dev_free);
- DBG(dev, "printer_close\n");
return 0;
}
@@ -447,11 +450,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
- if (dev->interface < 0) {
- spin_unlock_irqrestore(&dev->lock, flags);
- mutex_unlock(&dev->lock_printer_io);
- return -ENODEV;
- }
+ 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.
@@ -459,6 +459,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
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;
@@ -492,6 +495,8 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
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;
}
/* We have data to return then copy it to the caller's buffer.*/
@@ -535,6 +540,9 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN;
}
+ if (dev->interface < 0)
+ goto out_disabled;
+
/* If we not returning all the data left in this RX request
* buffer then adjust the amount of data left in the buffer.
* Othewise if we are done with this RX request buffer then
@@ -564,6 +572,11 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
return bytes_copied;
else
return -EAGAIN;
+
+out_disabled:
+ spin_unlock_irqrestore(&dev->lock, flags);
+ mutex_unlock(&dev->lock_printer_io);
+ return -ENODEV;
}
static ssize_t
@@ -584,11 +597,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
mutex_lock(&dev->lock_printer_io);
spin_lock_irqsave(&dev->lock, flags);
- if (dev->interface < 0) {
- spin_unlock_irqrestore(&dev->lock, flags);
- mutex_unlock(&dev->lock_printer_io);
- return -ENODEV;
- }
+ if (dev->interface < 0)
+ goto out_disabled;
/* Check if a printer reset happens while we have interrupts on */
dev->reset_printer = 0;
@@ -611,6 +621,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
wait_event_interruptible(dev->tx_wait,
(likely(!list_empty(&dev->tx_reqs))));
spin_lock_irqsave(&dev->lock, flags);
+ if (dev->interface < 0)
+ goto out_disabled;
}
while (likely(!list_empty(&dev->tx_reqs)) && len) {
@@ -660,6 +672,9 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return -EAGAIN;
}
+ if (dev->interface < 0)
+ goto out_disabled;
+
list_add(&req->list, &dev->tx_reqs_active);
/* here, we unlock, and only unlock, to avoid deadlock. */
@@ -672,6 +687,8 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
mutex_unlock(&dev->lock_printer_io);
return -EAGAIN;
}
+ if (dev->interface < 0)
+ goto out_disabled;
}
spin_unlock_irqrestore(&dev->lock, flags);
@@ -683,6 +700,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
return bytes_copied;
else
return -EAGAIN;
+
+out_disabled:
+ spin_unlock_irqrestore(&dev->lock, flags);
+ mutex_unlock(&dev->lock_printer_io);
+ return -ENODEV;
}
static int
@@ -848,8 +870,6 @@ static void printer_reset_interface(struct printer_dev *dev)
if (dev->interface < 0)
return;
- DBG(dev, "%s\n", __func__);
-
if (dev->in_ep->desc)
usb_ep_disable(dev->in_ep);
@@ -887,8 +907,6 @@ static void printer_soft_reset(struct printer_dev *dev)
{
struct usb_request *req;
- INFO(dev, "Received Printer Reset Request\n");
-
if (usb_ep_disable(dev->in_ep))
DBG(dev, "Failed to disable USB in_ep\n");
if (usb_ep_disable(dev->out_ep))
@@ -1000,16 +1018,16 @@ static int printer_func_setup(struct usb_function *f,
if ((wIndex>>8) != dev->interface)
break;
- if (!dev->pnp_string) {
+ if (!*dev->pnp_string) {
value = 0;
break;
}
- value = strlen(dev->pnp_string);
+ value = strlen(*dev->pnp_string);
buf[0] = (value >> 8) & 0xFF;
buf[1] = value & 0xFF;
- memcpy(buf + 2, dev->pnp_string, value);
+ memcpy(buf + 2, *dev->pnp_string, value);
DBG(dev, "1284 PNP String: %x %s\n", value,
- dev->pnp_string);
+ *dev->pnp_string);
break;
case GET_PORT_STATUS: /* Get Port Status */
@@ -1125,7 +1143,7 @@ autoconf_fail:
/* Setup the sysfs files for the printer gadget. */
devt = MKDEV(major, dev->minor);
- pdev = device_create(usb_gadget_class, NULL, devt,
+ pdev = device_create(&usb_gadget_class, NULL, devt,
NULL, "g_printer%d", dev->minor);
if (IS_ERR(pdev)) {
ERROR(dev, "Failed to create device: g_printer\n");
@@ -1148,7 +1166,7 @@ autoconf_fail:
return 0;
fail_cdev_add:
- device_destroy(usb_gadget_class, devt);
+ device_destroy(&usb_gadget_class, devt);
fail_rx_reqs:
while (!list_empty(&dev->rx_reqs)) {
@@ -1185,8 +1203,6 @@ static void printer_func_disable(struct usb_function *f)
{
struct printer_dev *dev = func_to_printer(f);
- DBG(dev, "%s\n", __func__);
-
printer_reset_interface(dev);
}
@@ -1218,8 +1234,8 @@ static ssize_t f_printer_opts_pnp_string_show(struct config_item *item,
if (!opts->pnp_string)
goto unlock;
- result = strlcpy(page, opts->pnp_string, PAGE_SIZE);
- if (result >= PAGE_SIZE) {
+ result = strscpy(page, opts->pnp_string, PAGE_SIZE);
+ if (result < 1) {
result = PAGE_SIZE;
} else if (page[result - 1] != '\n' && result + 1 < PAGE_SIZE) {
page[result++] = '\n';
@@ -1316,9 +1332,9 @@ static inline int gprinter_get_minor(void)
{
int ret;
- ret = ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+ ret = ida_alloc(&printer_ida, GFP_KERNEL);
if (ret >= PRINTER_MINORS) {
- ida_simple_remove(&printer_ida, ret);
+ ida_free(&printer_ida, ret);
ret = -ENODEV;
}
@@ -1327,7 +1343,7 @@ static inline int gprinter_get_minor(void)
static inline void gprinter_put_minor(int minor)
{
- ida_simple_remove(&printer_ida, minor);
+ ida_free(&printer_ida, minor);
}
static int gprinter_setup(int);
@@ -1417,7 +1433,7 @@ static void printer_func_unbind(struct usb_configuration *c,
dev = func_to_printer(f);
- device_destroy(usb_gadget_class, MKDEV(major, dev->minor));
+ device_destroy(&usb_gadget_class, MKDEV(major, dev->minor));
/* Remove Character Device */
cdev_del(&dev->printer_cdev);
@@ -1475,7 +1491,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
kref_init(&dev->kref);
++opts->refcnt;
dev->minor = opts->minor;
- dev->pnp_string = opts->pnp_string;
+ dev->pnp_string = &opts->pnp_string;
dev->q_len = opts->q_len;
mutex_unlock(&opts->lock);
@@ -1511,6 +1527,7 @@ static struct usb_function *gprinter_alloc(struct usb_function_instance *fi)
}
DECLARE_USB_FUNCTION_INIT(printer, gprinter_alloc_inst, gprinter_alloc);
+MODULE_DESCRIPTION("USB printer function driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Craig Nadler");
@@ -1519,19 +1536,14 @@ static int gprinter_setup(int count)
int status;
dev_t devt;
- usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
- if (IS_ERR(usb_gadget_class)) {
- status = PTR_ERR(usb_gadget_class);
- usb_gadget_class = NULL;
- pr_err("unable to create usb_gadget class %d\n", status);
+ status = class_register(&usb_gadget_class);
+ if (status)
return status;
- }
status = alloc_chrdev_region(&devt, 0, count, "USB printer gadget");
if (status) {
pr_err("alloc_chrdev_region %d\n", status);
- class_destroy(usb_gadget_class);
- usb_gadget_class = NULL;
+ class_unregister(&usb_gadget_class);
return status;
}
@@ -1547,6 +1559,5 @@ static void gprinter_cleanup(void)
unregister_chrdev_region(MKDEV(major, 0), minors);
major = minors = 0;
}
- class_destroy(usb_gadget_class);
- usb_gadget_class = NULL;
+ class_unregister(&usb_gadget_class);
}