[PATCH 11/20] usb/gadget: make g_printer enumerate again

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This was broken in 2e87edf49 ("usb: gadget: make g_printer use
composite").
The USB-strings were not setup properly and were not used. No function
was added which results in an empty USB config.
While fixing this, the interface number is now auto generated and not
hard coded to 0.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---
 drivers/usb/gadget/printer.c |  123 +++++++++++++++++++++---------------------
 1 file changed, 61 insertions(+), 62 deletions(-)

diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c
index 39279e2..aeeeae2 100644
--- a/drivers/usb/gadget/printer.c
+++ b/drivers/usb/gadget/printer.c
@@ -139,18 +139,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,
@@ -160,16 +156,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 */
@@ -258,9 +250,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 */
 };
 
@@ -869,25 +861,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);
@@ -970,7 +950,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];
@@ -981,7 +961,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;
@@ -990,7 +970,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);
@@ -1018,6 +998,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;
 }
 
@@ -1033,7 +1044,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;
 }
 
@@ -1105,13 +1117,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;
@@ -1123,6 +1136,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");
@@ -1167,26 +1184,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) {
@@ -1213,9 +1210,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) {
@@ -1248,8 +1242,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:
@@ -1266,6 +1258,13 @@ static int __init printer_bind(struct usb_composite_dev *cdev)
 {
 	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);
 	if (ret)
 		return ret;
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux