|
@@ -138,18 +138,14 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR);
|
|
|
* descriptors are built on demand.
|
|
|
*/
|
|
|
|
|
|
-#define STRING_MANUFACTURER 1
|
|
|
-#define STRING_PRODUCT 2
|
|
|
-#define STRING_SERIALNUM 3
|
|
|
+#define STRING_MANUFACTURER 0
|
|
|
+#define STRING_PRODUCT 1
|
|
|
+#define STRING_SERIALNUM 2
|
|
|
|
|
|
/* holds our biggest descriptor */
|
|
|
#define USB_DESC_BUFSIZE 256
|
|
|
#define USB_BUFSIZE 8192
|
|
|
|
|
|
-/* This device advertises one configuration. */
|
|
|
-#define DEV_CONFIG_VALUE 1
|
|
|
-#define PRINTER_INTERFACE 0
|
|
|
-
|
|
|
static struct usb_device_descriptor device_desc = {
|
|
|
.bLength = sizeof device_desc,
|
|
|
.bDescriptorType = USB_DT_DEVICE,
|
|
@@ -159,16 +155,12 @@ static struct usb_device_descriptor device_desc = {
|
|
|
.bDeviceProtocol = 0,
|
|
|
.idVendor = cpu_to_le16(PRINTER_VENDOR_NUM),
|
|
|
.idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM),
|
|
|
- .iManufacturer = STRING_MANUFACTURER,
|
|
|
- .iProduct = STRING_PRODUCT,
|
|
|
- .iSerialNumber = STRING_SERIALNUM,
|
|
|
.bNumConfigurations = 1
|
|
|
};
|
|
|
|
|
|
static struct usb_interface_descriptor intf_desc = {
|
|
|
.bLength = sizeof intf_desc,
|
|
|
.bDescriptorType = USB_DT_INTERFACE,
|
|
|
- .bInterfaceNumber = PRINTER_INTERFACE,
|
|
|
.bNumEndpoints = 2,
|
|
|
.bInterfaceClass = USB_CLASS_PRINTER,
|
|
|
.bInterfaceSubClass = 1, /* Printer Sub-Class */
|
|
@@ -257,9 +249,9 @@ static char pnp_string [1024] =
|
|
|
|
|
|
/* static strings, in UTF-8 */
|
|
|
static struct usb_string strings [] = {
|
|
|
- { STRING_MANUFACTURER, manufacturer, },
|
|
|
- { STRING_PRODUCT, product_desc, },
|
|
|
- { STRING_SERIALNUM, serial_num, },
|
|
|
+ [STRING_MANUFACTURER].s = manufacturer,
|
|
|
+ [STRING_PRODUCT].s = product_desc,
|
|
|
+ [STRING_SERIALNUM].s = serial_num,
|
|
|
{ } /* end of list */
|
|
|
};
|
|
|
|
|
@@ -868,25 +860,13 @@ static int set_interface(struct printer_dev *dev, unsigned number)
|
|
|
int result = 0;
|
|
|
|
|
|
/* Free the current interface */
|
|
|
- switch (dev->interface) {
|
|
|
- case PRINTER_INTERFACE:
|
|
|
- printer_reset_interface(dev);
|
|
|
- break;
|
|
|
- }
|
|
|
+ printer_reset_interface(dev);
|
|
|
|
|
|
- switch (number) {
|
|
|
- case PRINTER_INTERFACE:
|
|
|
- result = set_printer_interface(dev);
|
|
|
- if (result) {
|
|
|
- printer_reset_interface(dev);
|
|
|
- } else {
|
|
|
- dev->interface = PRINTER_INTERFACE;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- result = -EINVAL;
|
|
|
- /* FALL THROUGH */
|
|
|
- }
|
|
|
+ result = set_printer_interface(dev);
|
|
|
+ if (result)
|
|
|
+ printer_reset_interface(dev);
|
|
|
+ else
|
|
|
+ dev->interface = number;
|
|
|
|
|
|
if (!result)
|
|
|
INFO(dev, "Using interface %x\n", number);
|
|
@@ -969,7 +949,7 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
switch (ctrl->bRequest) {
|
|
|
case 0: /* Get the IEEE-1284 PNP String */
|
|
|
/* Only one printer interface is supported. */
|
|
|
- if ((wIndex>>8) != PRINTER_INTERFACE)
|
|
|
+ if ((wIndex>>8) != dev->interface)
|
|
|
break;
|
|
|
|
|
|
value = (pnp_string[0]<<8)|pnp_string[1];
|
|
@@ -980,7 +960,7 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
|
|
|
case 1: /* Get Port Status */
|
|
|
/* Only one printer interface is supported. */
|
|
|
- if (wIndex != PRINTER_INTERFACE)
|
|
|
+ if (wIndex != dev->interface)
|
|
|
break;
|
|
|
|
|
|
*(u8 *)req->buf = dev->printer_status;
|
|
@@ -989,7 +969,7 @@ static int printer_func_setup(struct usb_function *f,
|
|
|
|
|
|
case 2: /* Soft Reset */
|
|
|
/* Only one printer interface is supported. */
|
|
|
- if (wIndex != PRINTER_INTERFACE)
|
|
|
+ if (wIndex != dev->interface)
|
|
|
break;
|
|
|
|
|
|
printer_soft_reset(dev);
|
|
@@ -1017,6 +997,37 @@ unknown:
|
|
|
static int __init printer_func_bind(struct usb_configuration *c,
|
|
|
struct usb_function *f)
|
|
|
{
|
|
|
+ struct printer_dev *dev = container_of(f, struct printer_dev, function);
|
|
|
+ struct usb_composite_dev *cdev = c->cdev;
|
|
|
+ struct usb_ep *in_ep, *out_ep;
|
|
|
+ int id;
|
|
|
+
|
|
|
+ id = usb_interface_id(c, f);
|
|
|
+ if (id < 0)
|
|
|
+ return id;
|
|
|
+ intf_desc.bInterfaceNumber = id;
|
|
|
+
|
|
|
+ /* all we really need is bulk IN/OUT */
|
|
|
+ in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc);
|
|
|
+ if (!in_ep) {
|
|
|
+autoconf_fail:
|
|
|
+ dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n",
|
|
|
+ cdev->gadget->name);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ in_ep->driver_data = in_ep; /* claim */
|
|
|
+
|
|
|
+ out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
|
|
|
+ if (!out_ep)
|
|
|
+ goto autoconf_fail;
|
|
|
+ out_ep->driver_data = out_ep; /* claim */
|
|
|
+
|
|
|
+ /* assumes that all endpoints are dual-speed */
|
|
|
+ hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
|
|
|
+ hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
|
|
|
+
|
|
|
+ dev->in_ep = in_ep;
|
|
|
+ dev->out_ep = out_ep;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1032,7 +1043,8 @@ static int printer_func_set_alt(struct usb_function *f,
|
|
|
int ret = -ENOTSUPP;
|
|
|
|
|
|
if (!alt)
|
|
|
- ret = set_interface(dev, PRINTER_INTERFACE);
|
|
|
+ ret = set_interface(dev, intf);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -1104,13 +1116,14 @@ 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;
|
|
|
int gcnum;
|
|
|
size_t len;
|
|
|
u32 i;
|
|
|
struct usb_request *req;
|
|
|
|
|
|
+ usb_ep_autoconfig_reset(gadget);
|
|
|
+
|
|
|
dev = &usb_printer_gadget;
|
|
|
|
|
|
dev->function.name = shortname;
|
|
@@ -1122,6 +1135,10 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|
|
dev->function.set_alt = printer_func_set_alt;
|
|
|
dev->function.disable = printer_func_disable;
|
|
|
|
|
|
+ status = usb_add_function(c, &dev->function);
|
|
|
+ if (status)
|
|
|
+ return status;
|
|
|
+
|
|
|
/* Setup the sysfs files for the printer gadget. */
|
|
|
dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno,
|
|
|
NULL, "g_printer");
|
|
@@ -1166,26 +1183,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
|
|
|
pnp_string[0] = (len >> 8) & 0xFF;
|
|
|
pnp_string[1] = len & 0xFF;
|
|
|
|
|
|
- /* all we really need is bulk IN/OUT */
|
|
|
- usb_ep_autoconfig_reset(gadget);
|
|
|
- in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc);
|
|
|
- if (!in_ep) {
|
|
|
-autoconf_fail:
|
|
|
- dev_err(&gadget->dev, "can't autoconfigure on %s\n",
|
|
|
- gadget->name);
|
|
|
- return -ENODEV;
|
|
|
- }
|
|
|
- in_ep->driver_data = in_ep; /* claim */
|
|
|
-
|
|
|
- out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc);
|
|
|
- if (!out_ep)
|
|
|
- goto autoconf_fail;
|
|
|
- out_ep->driver_data = out_ep; /* claim */
|
|
|
-
|
|
|
- /* assumes that all endpoints are dual-speed */
|
|
|
- hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
|
|
|
- hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
|
|
|
-
|
|
|
usb_gadget_set_selfpowered(gadget);
|
|
|
|
|
|
if (gadget->is_otg) {
|
|
@@ -1212,9 +1209,6 @@ autoconf_fail:
|
|
|
dev->current_rx_bytes = 0;
|
|
|
dev->current_rx_buf = NULL;
|
|
|
|
|
|
- dev->in_ep = in_ep;
|
|
|
- dev->out_ep = out_ep;
|
|
|
-
|
|
|
for (i = 0; i < QLEN; i++) {
|
|
|
req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL);
|
|
|
if (!req) {
|
|
@@ -1247,8 +1241,6 @@ autoconf_fail:
|
|
|
dev->gadget = gadget;
|
|
|
|
|
|
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:
|
|
@@ -1263,7 +1255,17 @@ static int printer_unbind(struct usb_composite_dev *cdev)
|
|
|
|
|
|
static int __init printer_bind(struct usb_composite_dev *cdev)
|
|
|
{
|
|
|
- return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = usb_string_ids_tab(cdev, strings);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ device_desc.iManufacturer = strings[STRING_MANUFACTURER].id;
|
|
|
+ device_desc.iProduct = strings[STRING_PRODUCT].id;
|
|
|
+ device_desc.iSerialNumber = strings[STRING_SERIALNUM].id;
|
|
|
+
|
|
|
+ ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config);
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
static __refdata struct usb_composite_driver printer_driver = {
|