|
@@ -51,6 +51,7 @@
|
|
|
* the runtime footprint, and giving us at least some parts of what
|
|
|
* a "gcc --combine ... part1.c part2.c part3.c ... " build would.
|
|
|
*/
|
|
|
+#include "composite.c"
|
|
|
#include "usbstring.c"
|
|
|
#include "config.c"
|
|
|
#include "epautoconf.c"
|
|
@@ -75,8 +76,6 @@ struct printer_dev {
|
|
|
/* lock buffer lists during read/write calls */
|
|
|
struct mutex lock_printer_io;
|
|
|
struct usb_gadget *gadget;
|
|
|
- struct usb_request *req; /* for control responses */
|
|
|
- u8 config;
|
|
|
s8 interface;
|
|
|
struct usb_ep *in_ep, *out_ep;
|
|
|
|
|
@@ -100,6 +99,7 @@ struct printer_dev {
|
|
|
struct device *pdev;
|
|
|
u8 printer_cdev_open;
|
|
|
wait_queue_head_t wait;
|
|
|
+ struct usb_function function;
|
|
|
};
|
|
|
|
|
|
static struct printer_dev usb_printer_gadget;
|
|
@@ -120,26 +120,6 @@ static struct printer_dev usb_printer_gadget;
|
|
|
* parameters are in UTF-8 (superset of ASCII's 7 bit characters).
|
|
|
*/
|
|
|
|
|
|
-static ushort idVendor;
|
|
|
-module_param(idVendor, ushort, S_IRUGO);
|
|
|
-MODULE_PARM_DESC(idVendor, "USB Vendor ID");
|
|
|
-
|
|
|
-static ushort idProduct;
|
|
|
-module_param(idProduct, ushort, S_IRUGO);
|
|
|
-MODULE_PARM_DESC(idProduct, "USB Product ID");
|
|
|
-
|
|
|
-static ushort bcdDevice;
|
|
|
-module_param(bcdDevice, ushort, S_IRUGO);
|
|
|
-MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)");
|
|
|
-
|
|
|
-static char *iManufacturer;
|
|
|
-module_param(iManufacturer, charp, S_IRUGO);
|
|
|
-MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string");
|
|
|
-
|
|
|
-static char *iProduct;
|
|
|
-module_param(iProduct, charp, S_IRUGO);
|
|
|
-MODULE_PARM_DESC(iProduct, "USB Product string");
|
|
|
-
|
|
|
static char *iSerialNum;
|
|
|
module_param(iSerialNum, charp, S_IRUGO);
|
|
|
MODULE_PARM_DESC(iSerialNum, "1");
|
|
@@ -156,39 +136,6 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
-#define xprintk(d, level, fmt, args...) \
|
|
|
- printk(level "%s: " fmt, DRIVER_DESC, ## args)
|
|
|
-
|
|
|
-#ifdef DEBUG
|
|
|
-#define DBG(dev, fmt, args...) \
|
|
|
- xprintk(dev, KERN_DEBUG, fmt, ## args)
|
|
|
-#else
|
|
|
-#define DBG(dev, fmt, args...) \
|
|
|
- do { } while (0)
|
|
|
-#endif /* DEBUG */
|
|
|
-
|
|
|
-#ifdef VERBOSE
|
|
|
-#define VDBG(dev, fmt, args...) \
|
|
|
- xprintk(dev, KERN_DEBUG, fmt, ## args)
|
|
|
-#else
|
|
|
-#define VDBG(dev, fmt, args...) \
|
|
|
- do { } while (0)
|
|
|
-#endif /* VERBOSE */
|
|
|
-
|
|
|
-#define ERROR(dev, fmt, args...) \
|
|
|
- xprintk(dev, KERN_ERR, fmt, ## args)
|
|
|
-#define WARNING(dev, fmt, args...) \
|
|
|
- xprintk(dev, KERN_WARNING, fmt, ## args)
|
|
|
-#define INFO(dev, fmt, args...) \
|
|
|
- xprintk(dev, KERN_INFO, fmt, ## args)
|
|
|
-
|
|
|
-/*-------------------------------------------------------------------------*/
|
|
|
-
|
|
|
-/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly
|
|
|
- * ep0 implementation: descriptors, config management, setup().
|
|
|
- * also optional class-specific notification interrupt transfer.
|
|
|
- */
|
|
|
-
|
|
|
/*
|
|
|
* DESCRIPTORS ... most are static, but strings and (full) configuration
|
|
|
* descriptors are built on demand.
|
|
@@ -221,24 +168,6 @@ static struct usb_device_descriptor device_desc = {
|
|
|
.bNumConfigurations = 1
|
|
|
};
|
|
|
|
|
|
-static struct usb_otg_descriptor otg_desc = {
|
|
|
- .bLength = sizeof otg_desc,
|
|
|
- .bDescriptorType = USB_DT_OTG,
|
|
|
- .bmAttributes = USB_OTG_SRP
|
|
|
-};
|
|
|
-
|
|
|
-static struct usb_config_descriptor config_desc = {
|
|
|
- .bLength = sizeof config_desc,
|
|
|
- .bDescriptorType = USB_DT_CONFIG,
|
|
|
-
|
|
|
- /* compute wTotalLength on the fly */
|
|
|
- .bNumInterfaces = 1,
|
|
|
- .bConfigurationValue = DEV_CONFIG_VALUE,
|
|
|
- .iConfiguration = 0,
|
|
|
- .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
|
|
|
- .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2,
|
|
|
-};
|
|
|
-
|
|
|
static struct usb_interface_descriptor intf_desc = {
|
|
|
.bLength = sizeof intf_desc,
|
|
|
.bDescriptorType = USB_DT_INTERFACE,
|
|
@@ -264,8 +193,7 @@ static struct usb_endpoint_descriptor fs_ep_out_desc = {
|
|
|
.bmAttributes = USB_ENDPOINT_XFER_BULK
|
|
|
};
|
|
|
|
|
|
-static const struct usb_descriptor_header *fs_printer_function [11] = {
|
|
|
- (struct usb_descriptor_header *) &otg_desc,
|
|
|
+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,
|
|
@@ -299,14 +227,24 @@ static struct usb_qualifier_descriptor dev_qualifier = {
|
|
|
.bNumConfigurations = 1
|
|
|
};
|
|
|
|
|
|
-static const struct usb_descriptor_header *hs_printer_function [11] = {
|
|
|
- (struct usb_descriptor_header *) &otg_desc,
|
|
|
+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
|
|
|
};
|
|
|
|
|
|
+static struct usb_otg_descriptor otg_descriptor = {
|
|
|
+ .bLength = sizeof otg_descriptor,
|
|
|
+ .bDescriptorType = USB_DT_OTG,
|
|
|
+ .bmAttributes = USB_OTG_SRP,
|
|
|
+};
|
|
|
+
|
|
|
+static const struct usb_descriptor_header *otg_desc[] = {
|
|
|
+ (struct usb_descriptor_header *) &otg_descriptor,
|
|
|
+ NULL,
|
|
|
+};
|
|
|
+
|
|
|
/* maxpacket and other transfer characteristics vary by speed. */
|
|
|
#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs))
|
|
|
|
|
@@ -328,11 +266,16 @@ static struct usb_string strings [] = {
|
|
|
{ } /* end of list */
|
|
|
};
|
|
|
|
|
|
-static struct usb_gadget_strings stringtab = {
|
|
|
+static struct usb_gadget_strings stringtab_dev = {
|
|
|
.language = 0x0409, /* en-us */
|
|
|
.strings = strings,
|
|
|
};
|
|
|
|
|
|
+static struct usb_gadget_strings *dev_strings[] = {
|
|
|
+ &stringtab_dev,
|
|
|
+ NULL,
|
|
|
+};
|
|
|
+
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
static struct usb_request *
|
|
@@ -922,78 +865,8 @@ static void printer_reset_interface(struct printer_dev *dev)
|
|
|
dev->interface = -1;
|
|
|
}
|
|
|
|
|
|
-/* change our operational config. must agree with the code
|
|
|
- * that returns config descriptors, and altsetting code.
|
|
|
- */
|
|
|
-static int
|
|
|
-printer_set_config(struct printer_dev *dev, unsigned number)
|
|
|
-{
|
|
|
- int result = 0;
|
|
|
- struct usb_gadget *gadget = dev->gadget;
|
|
|
-
|
|
|
- switch (number) {
|
|
|
- case DEV_CONFIG_VALUE:
|
|
|
- result = 0;
|
|
|
- break;
|
|
|
- default:
|
|
|
- result = -EINVAL;
|
|
|
- /* FALL THROUGH */
|
|
|
- case 0:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (result) {
|
|
|
- usb_gadget_vbus_draw(dev->gadget,
|
|
|
- dev->gadget->is_otg ? 8 : 100);
|
|
|
- } else {
|
|
|
- unsigned power;
|
|
|
-
|
|
|
- power = 2 * config_desc.bMaxPower;
|
|
|
- usb_gadget_vbus_draw(dev->gadget, power);
|
|
|
-
|
|
|
- dev->config = number;
|
|
|
- INFO(dev, "%s config #%d: %d mA, %s\n",
|
|
|
- usb_speed_string(gadget->speed),
|
|
|
- number, power, driver_desc);
|
|
|
- }
|
|
|
- return result;
|
|
|
-}
|
|
|
-
|
|
|
-static int
|
|
|
-config_buf(enum usb_device_speed speed, u8 *buf, u8 type, unsigned index,
|
|
|
- int is_otg)
|
|
|
-{
|
|
|
- int len;
|
|
|
- const struct usb_descriptor_header **function;
|
|
|
- int hs = (speed == USB_SPEED_HIGH);
|
|
|
-
|
|
|
- if (type == USB_DT_OTHER_SPEED_CONFIG)
|
|
|
- hs = !hs;
|
|
|
-
|
|
|
- if (hs) {
|
|
|
- function = hs_printer_function;
|
|
|
- } else {
|
|
|
- function = fs_printer_function;
|
|
|
- }
|
|
|
-
|
|
|
- if (index >= device_desc.bNumConfigurations)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- /* for now, don't advertise srp-only devices */
|
|
|
- if (!is_otg)
|
|
|
- function++;
|
|
|
-
|
|
|
- len = usb_gadget_config_buf(&config_desc, buf, USB_DESC_BUFSIZE,
|
|
|
- function);
|
|
|
- if (len < 0)
|
|
|
- return len;
|
|
|
- ((struct usb_config_descriptor *) buf)->bDescriptorType = type;
|
|
|
- return len;
|
|
|
-}
|
|
|
-
|
|
|
/* Change our operational Interface. */
|
|
|
-static int
|
|
|
-set_interface(struct printer_dev *dev, unsigned number)
|
|
|
+static int set_interface(struct printer_dev *dev, unsigned number)
|
|
|
{
|
|
|
int result = 0;
|
|
|
|
|
@@ -1024,14 +897,6 @@ set_interface(struct printer_dev *dev, unsigned number)
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
-static void printer_setup_complete(struct usb_ep *ep, struct usb_request *req)
|
|
|
-{
|
|
|
- if (req->status || req->actual != req->length)
|
|
|
- DBG((struct printer_dev *) ep->driver_data,
|
|
|
- "setup complete --> %d, %d/%d\n",
|
|
|
- req->status, req->actual, req->length);
|
|
|
-}
|
|
|
-
|
|
|
static void printer_soft_reset(struct printer_dev *dev)
|
|
|
{
|
|
|
struct usb_request *req;
|
|
@@ -1088,11 +953,12 @@ static void printer_soft_reset(struct printer_dev *dev)
|
|
|
* The setup() callback implements all the ep0 functionality that's not
|
|
|
* handled lower down.
|
|
|
*/
|
|
|
-static int
|
|
|
-printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
|
+static int printer_func_setup(struct usb_function *f,
|
|
|
+ const struct usb_ctrlrequest *ctrl)
|
|
|
{
|
|
|
- struct printer_dev *dev = get_gadget_data(gadget);
|
|
|
- struct usb_request *req = dev->req;
|
|
|
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
|
|
|
+ struct usb_composite_dev *cdev = f->config->cdev;
|
|
|
+ struct usb_request *req = cdev->req;
|
|
|
int value = -EOPNOTSUPP;
|
|
|
u16 wIndex = le16_to_cpu(ctrl->wIndex);
|
|
|
u16 wValue = le16_to_cpu(ctrl->wValue);
|
|
@@ -1101,100 +967,7 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|
|
|
DBG(dev, "ctrl req%02x.%02x v%04x i%04x l%d\n",
|
|
|
ctrl->bRequestType, ctrl->bRequest, wValue, wIndex, wLength);
|
|
|
|
|
|
- req->complete = printer_setup_complete;
|
|
|
-
|
|
|
switch (ctrl->bRequestType&USB_TYPE_MASK) {
|
|
|
-
|
|
|
- case USB_TYPE_STANDARD:
|
|
|
- switch (ctrl->bRequest) {
|
|
|
-
|
|
|
- case USB_REQ_GET_DESCRIPTOR:
|
|
|
- if (ctrl->bRequestType != USB_DIR_IN)
|
|
|
- break;
|
|
|
- switch (wValue >> 8) {
|
|
|
-
|
|
|
- case USB_DT_DEVICE:
|
|
|
- device_desc.bMaxPacketSize0 =
|
|
|
- gadget->ep0->maxpacket;
|
|
|
- value = min(wLength, (u16) sizeof device_desc);
|
|
|
- memcpy(req->buf, &device_desc, value);
|
|
|
- break;
|
|
|
- case USB_DT_DEVICE_QUALIFIER:
|
|
|
- if (!gadget_is_dualspeed(gadget))
|
|
|
- break;
|
|
|
- /*
|
|
|
- * assumes ep0 uses the same value for both
|
|
|
- * speeds
|
|
|
- */
|
|
|
- dev_qualifier.bMaxPacketSize0 =
|
|
|
- gadget->ep0->maxpacket;
|
|
|
- value = min(wLength,
|
|
|
- (u16) sizeof dev_qualifier);
|
|
|
- memcpy(req->buf, &dev_qualifier, value);
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_DT_OTHER_SPEED_CONFIG:
|
|
|
- if (!gadget_is_dualspeed(gadget))
|
|
|
- break;
|
|
|
- /* FALLTHROUGH */
|
|
|
- case USB_DT_CONFIG:
|
|
|
- value = config_buf(gadget->speed, req->buf,
|
|
|
- wValue >> 8,
|
|
|
- wValue & 0xff,
|
|
|
- gadget->is_otg);
|
|
|
- if (value >= 0)
|
|
|
- value = min(wLength, (u16) value);
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_DT_STRING:
|
|
|
- value = usb_gadget_get_string(&stringtab,
|
|
|
- wValue & 0xff, req->buf);
|
|
|
- if (value >= 0)
|
|
|
- value = min(wLength, (u16) value);
|
|
|
- break;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_REQ_SET_CONFIGURATION:
|
|
|
- if (ctrl->bRequestType != 0)
|
|
|
- break;
|
|
|
- if (gadget->a_hnp_support)
|
|
|
- DBG(dev, "HNP available\n");
|
|
|
- else if (gadget->a_alt_hnp_support)
|
|
|
- DBG(dev, "HNP needs a different root port\n");
|
|
|
- value = printer_set_config(dev, wValue);
|
|
|
- if (!value)
|
|
|
- value = set_interface(dev, PRINTER_INTERFACE);
|
|
|
- break;
|
|
|
- case USB_REQ_GET_CONFIGURATION:
|
|
|
- if (ctrl->bRequestType != USB_DIR_IN)
|
|
|
- break;
|
|
|
- *(u8 *)req->buf = dev->config;
|
|
|
- value = min(wLength, (u16) 1);
|
|
|
- break;
|
|
|
-
|
|
|
- case USB_REQ_SET_INTERFACE:
|
|
|
- if (ctrl->bRequestType != USB_RECIP_INTERFACE ||
|
|
|
- !dev->config)
|
|
|
- break;
|
|
|
-
|
|
|
- value = set_interface(dev, PRINTER_INTERFACE);
|
|
|
- break;
|
|
|
- case USB_REQ_GET_INTERFACE:
|
|
|
- if (ctrl->bRequestType !=
|
|
|
- (USB_DIR_IN|USB_RECIP_INTERFACE)
|
|
|
- || !dev->config)
|
|
|
- break;
|
|
|
-
|
|
|
- *(u8 *)req->buf = dev->interface;
|
|
|
- value = min(wLength, (u16) 1);
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- goto unknown;
|
|
|
- }
|
|
|
- break;
|
|
|
-
|
|
|
case USB_TYPE_CLASS:
|
|
|
switch (ctrl->bRequest) {
|
|
|
case 0: /* Get the IEEE-1284 PNP String */
|
|
@@ -1240,44 +1013,50 @@ unknown:
|
|
|
wValue, wIndex, wLength);
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
- /* respond with data transfer before status phase? */
|
|
|
- if (value >= 0) {
|
|
|
- req->length = value;
|
|
|
- req->zero = value < wLength;
|
|
|
- value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
|
|
|
- if (value < 0) {
|
|
|
- DBG(dev, "ep_queue --> %d\n", value);
|
|
|
- req->status = 0;
|
|
|
- printer_setup_complete(gadget->ep0, req);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* host either stalls (value < 0) or reports success */
|
|
|
return value;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-printer_disconnect(struct usb_gadget *gadget)
|
|
|
+static int __init printer_func_bind(struct usb_configuration *c,
|
|
|
+ struct usb_function *f)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static void printer_func_unbind(struct usb_configuration *c,
|
|
|
+ struct usb_function *f)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+static int printer_func_set_alt(struct usb_function *f,
|
|
|
+ unsigned intf, unsigned alt)
|
|
|
{
|
|
|
- struct printer_dev *dev = get_gadget_data(gadget);
|
|
|
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
|
|
|
+ int ret = -ENOTSUPP;
|
|
|
+
|
|
|
+ if (!alt)
|
|
|
+ ret = set_interface(dev, PRINTER_INTERFACE);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void printer_func_disable(struct usb_function *f)
|
|
|
+{
|
|
|
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
|
|
|
unsigned long flags;
|
|
|
|
|
|
DBG(dev, "%s\n", __func__);
|
|
|
|
|
|
spin_lock_irqsave(&dev->lock, flags);
|
|
|
-
|
|
|
printer_reset_interface(dev);
|
|
|
-
|
|
|
spin_unlock_irqrestore(&dev->lock, flags);
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-printer_unbind(struct usb_gadget *gadget)
|
|
|
+static void printer_cfg_unbind(struct usb_configuration *c)
|
|
|
{
|
|
|
- struct printer_dev *dev = get_gadget_data(gadget);
|
|
|
+ struct printer_dev *dev;
|
|
|
struct usb_request *req;
|
|
|
|
|
|
+ dev = &usb_printer_gadget;
|
|
|
|
|
|
DBG(dev, "%s\n", __func__);
|
|
|
|
|
@@ -1315,18 +1094,18 @@ printer_unbind(struct usb_gadget *gadget)
|
|
|
list_del(&req->list);
|
|
|
printer_req_free(dev->out_ep, req);
|
|
|
}
|
|
|
-
|
|
|
- if (dev->req) {
|
|
|
- printer_req_free(gadget->ep0, dev->req);
|
|
|
- dev->req = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- set_gadget_data(gadget, NULL);
|
|
|
}
|
|
|
|
|
|
-static int __init
|
|
|
-printer_bind(struct usb_gadget *gadget)
|
|
|
+static struct usb_configuration printer_cfg_driver = {
|
|
|
+ .label = "printer",
|
|
|
+ .unbind = printer_cfg_unbind,
|
|
|
+ .bConfigurationValue = 1,
|
|
|
+ .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
|
|
|
+};
|
|
|
+
|
|
|
+static int __init printer_bind_config(struct usb_configuration *c)
|
|
|
{
|
|
|
+ struct usb_gadget *gadget = c->cdev->gadget;
|
|
|
struct printer_dev *dev;
|
|
|
struct usb_ep *in_ep, *out_ep;
|
|
|
int status = -ENOMEM;
|
|
@@ -1337,6 +1116,14 @@ printer_bind(struct usb_gadget *gadget)
|
|
|
|
|
|
dev = &usb_printer_gadget;
|
|
|
|
|
|
+ dev->function.name = shortname;
|
|
|
+ dev->function.descriptors = fs_printer_function;
|
|
|
+ dev->function.hs_descriptors = hs_printer_function;
|
|
|
+ dev->function.bind = printer_func_bind;
|
|
|
+ dev->function.setup = printer_func_setup;
|
|
|
+ dev->function.unbind = printer_func_unbind;
|
|
|
+ dev->function.set_alt = printer_func_set_alt;
|
|
|
+ dev->function.disable = printer_func_disable;
|
|
|
|
|
|
/* Setup the sysfs files for the printer gadget. */
|
|
|
dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
|
|
@@ -1372,29 +1159,6 @@ printer_bind(struct usb_gadget *gadget)
|
|
|
init_utsname()->sysname, init_utsname()->release,
|
|
|
gadget->name);
|
|
|
|
|
|
- device_desc.idVendor =
|
|
|
- cpu_to_le16(PRINTER_VENDOR_NUM);
|
|
|
- device_desc.idProduct =
|
|
|
- cpu_to_le16(PRINTER_PRODUCT_NUM);
|
|
|
-
|
|
|
- /* support optional vendor/distro customization */
|
|
|
- if (idVendor) {
|
|
|
- if (!idProduct) {
|
|
|
- dev_err(&gadget->dev, "idVendor needs idProduct!\n");
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
- device_desc.idVendor = cpu_to_le16(idVendor);
|
|
|
- device_desc.idProduct = cpu_to_le16(idProduct);
|
|
|
- if (bcdDevice)
|
|
|
- device_desc.bcdDevice = cpu_to_le16(bcdDevice);
|
|
|
- }
|
|
|
-
|
|
|
- if (iManufacturer)
|
|
|
- strlcpy(manufacturer, iManufacturer, sizeof manufacturer);
|
|
|
-
|
|
|
- if (iProduct)
|
|
|
- strlcpy(product_desc, iProduct, sizeof product_desc);
|
|
|
-
|
|
|
if (iSerialNum)
|
|
|
strlcpy(serial_num, iSerialNum, sizeof serial_num);
|
|
|
|
|
@@ -1428,8 +1192,9 @@ autoconf_fail:
|
|
|
usb_gadget_set_selfpowered(gadget);
|
|
|
|
|
|
if (gadget->is_otg) {
|
|
|
- otg_desc.bmAttributes |= USB_OTG_HNP,
|
|
|
- config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
|
+ otg_descriptor.bmAttributes |= USB_OTG_HNP;
|
|
|
+ printer_cfg_driver.descriptors = otg_desc;
|
|
|
+ printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
|
|
|
}
|
|
|
|
|
|
spin_lock_init(&dev->lock);
|
|
@@ -1443,7 +1208,6 @@ autoconf_fail:
|
|
|
init_waitqueue_head(&dev->tx_wait);
|
|
|
init_waitqueue_head(&dev->tx_flush_wait);
|
|
|
|
|
|
- dev->config = 0;
|
|
|
dev->interface = -1;
|
|
|
dev->printer_cdev_open = 0;
|
|
|
dev->printer_status = PRINTER_NOT_ERROR;
|
|
@@ -1454,14 +1218,6 @@ autoconf_fail:
|
|
|
dev->in_ep = in_ep;
|
|
|
dev->out_ep = out_ep;
|
|
|
|
|
|
- /* preallocate control message data and buffer */
|
|
|
- dev->req = printer_req_alloc(gadget->ep0, USB_DESC_BUFSIZE,
|
|
|
- GFP_KERNEL);
|
|
|
- if (!dev->req) {
|
|
|
- status = -ENOMEM;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
for (i = 0; i < QLEN; i++) {
|
|
|
req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
|
|
|
if (!req) {
|
|
@@ -1490,45 +1246,37 @@ autoconf_fail:
|
|
|
list_add(&req->list, &dev->rx_reqs);
|
|
|
}
|
|
|
|
|
|
- dev->req->complete = printer_setup_complete;
|
|
|
-
|
|
|
/* finish hookup to lower layer ... */
|
|
|
dev->gadget = gadget;
|
|
|
- set_gadget_data(gadget, dev);
|
|
|
- gadget->ep0->driver_data = dev;
|
|
|
|
|
|
INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc);
|
|
|
INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name,
|
|
|
in_ep->name);
|
|
|
-
|
|
|
return 0;
|
|
|
|
|
|
fail:
|
|
|
- printer_unbind(gadget);
|
|
|
+ printer_cfg_unbind(c);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-/*-------------------------------------------------------------------------*/
|
|
|
+static int printer_unbind(struct usb_composite_dev *cdev)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
-static struct usb_gadget_driver printer_driver = {
|
|
|
- .max_speed = USB_SPEED_HIGH,
|
|
|
+static int __init printer_bind(struct usb_composite_dev *cdev)
|
|
|
+{
|
|
|
+ return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
|
|
|
+}
|
|
|
|
|
|
- .function = (char *) driver_desc,
|
|
|
+static struct usb_composite_driver printer_driver = {
|
|
|
+ .name = shortname,
|
|
|
+ .dev = &device_desc,
|
|
|
+ .strings = dev_strings,
|
|
|
+ .max_speed = USB_SPEED_HIGH,
|
|
|
.unbind = printer_unbind,
|
|
|
-
|
|
|
- .setup = printer_setup,
|
|
|
- .disconnect = printer_disconnect,
|
|
|
-
|
|
|
- .driver = {
|
|
|
- .name = (char *) shortname,
|
|
|
- .owner = THIS_MODULE,
|
|
|
- },
|
|
|
};
|
|
|
|
|
|
-MODULE_DESCRIPTION(DRIVER_DESC);
|
|
|
-MODULE_AUTHOR("Craig Nadler");
|
|
|
-MODULE_LICENSE("GPL");
|
|
|
-
|
|
|
static int __init
|
|
|
init(void)
|
|
|
{
|
|
@@ -1537,23 +1285,23 @@ init(void)
|
|
|
usb_gadget_class = class_create(THIS_MODULE, "usb_printer_gadget");
|
|
|
if (IS_ERR(usb_gadget_class)) {
|
|
|
status = PTR_ERR(usb_gadget_class);
|
|
|
- ERROR(dev, "unable to create usb_gadget class %d\n", status);
|
|
|
+ pr_err("unable to create usb_gadget class %d\n", status);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
status = alloc_chrdev_region(&g_printer_devno, 0, 1,
|
|
|
"USB printer gadget");
|
|
|
if (status) {
|
|
|
- ERROR(dev, "alloc_chrdev_region %d\n", status);
|
|
|
+ pr_err("alloc_chrdev_region %d\n", status);
|
|
|
class_destroy(usb_gadget_class);
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
- status = usb_gadget_probe_driver(&printer_driver, printer_bind);
|
|
|
+ status = usb_composite_probe(&printer_driver, printer_bind);
|
|
|
if (status) {
|
|
|
class_destroy(usb_gadget_class);
|
|
|
unregister_chrdev_region(g_printer_devno, 1);
|
|
|
- DBG(dev, "usb_gadget_probe_driver %x\n", status);
|
|
|
+ pr_err("usb_gadget_probe_driver %x\n", status);
|
|
|
}
|
|
|
|
|
|
return status;
|
|
@@ -1563,15 +1311,14 @@ module_init(init);
|
|
|
static void __exit
|
|
|
cleanup(void)
|
|
|
{
|
|
|
- int status;
|
|
|
-
|
|
|
mutex_lock(&usb_printer_gadget.lock_printer_io);
|
|
|
- status = usb_gadget_unregister_driver(&printer_driver);
|
|
|
- if (status)
|
|
|
- ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
|
|
|
-
|
|
|
+ usb_composite_unregister(&printer_driver);
|
|
|
unregister_chrdev_region(g_printer_devno, 1);
|
|
|
class_destroy(usb_gadget_class);
|
|
|
mutex_unlock(&usb_printer_gadget.lock_printer_io);
|
|
|
}
|
|
|
module_exit(cleanup);
|
|
|
+
|
|
|
+MODULE_DESCRIPTION(DRIVER_DESC);
|
|
|
+MODULE_AUTHOR("Craig Nadler");
|
|
|
+MODULE_LICENSE("GPL");
|