[patch 4/8] The Composite Gadget itself.

Felipe Balbi <[email protected]>
Newsgroups gmane.linux.usb.devel
Message-ID <[email protected]>
patch-composite-device-functions.diff (text/plain, 8.9 KB)
	This gadget is built using a generic approach.
	To use this composite gadget, just load the gadget modules and plug-in
	the USB Cable.

	The g_midi.c file was not modified yet.

	Will come in a separate patch.

Signed-off-by: Felipe Balbi <[email protected]>
Signed-off-by: Ragner Magalhaes <[email protected]>
---

Index: linux-omap-2.6-ragner/drivers/usb/gadget/composite_functions.c
===================================================================
--- /dev/null
+++ linux-omap-2.6-ragner/drivers/usb/gadget/composite_functions.c
@@ -0,0 +1,304 @@
+/*
+ * composite_functions.c -- USB OMAP Layer for Composite Device Support
+ *
+ * Copyright 2006 (C) Instituto Nokia de Tecnologia - INdT
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of the License of (at you option) any later version.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
+#include <linux/timer.h>
+#include <linux/utsname.h>
+#include <linux/usb_ch9.h>
+#include <linux/usb_gadget.h>
+#include <linux/usb/composite.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/semaphore.h>
+#include <asm/system.h>
+#include <asm/unaligned.h>
+
+#include "gadget_chips.h"
+
+#define COMPOSITE_DESC		"Composite Driver"
+#define COMPOSITE_VERSION	"v1.0-alpha"
+
+
+static const char driver_desc [] = COMPOSITE_DESC;
+
+/* descriptors that are built on-demand */
+static char manufacturer [50];
+static char product_desc [40] = COMPOSITE_DESC;
+static char serial_number [20] = {"0"};
+
+/*-------------------------------------------------------------------------*/
+
+#define NUM_CONFIGS		1
+
+#define VENDOR_ID		0x0525 /* NetChip */
+#define PRODUCT_ID		0Xa4a6 /* Linux-USB Serial */
+#define COMPOSITE_CONFIG_NUMBER		1
+
+/* USB String IDs */
+#define COMPOSITE_MANUFACTURER_ID 	1
+#define COMPOSITE_PRODUCT_ID 		2
+#define COMPOSITE_SERIALNUMBER_ID 	3
+#define COMPOSITE_CONFIG_SRT_ID 	4
+
+MODULE_DESCRIPTION(COMPOSITE_DESC);
+MODULE_AUTHOR("Felipe Balbi, Ragner Magalhaes");
+MODULE_LICENSE("GPL");
+
+/* USB Strings, UTF8 */
+
+
+static struct usb_string composite_strings[] = {
+	{ COMPOSITE_MANUFACTURER_ID, manufacturer },
+	{ COMPOSITE_PRODUCT_ID, product_desc},
+	{ COMPOSITE_SERIALNUMBER_ID, serial_number },
+	{ COMPOSITE_CONFIG_SRT_ID, "Composite Alpha" },
+	{  } /* end */
+};
+static struct usb_gadget_strings composite_stringtable = {
+	.language		= 0x0409, /* en-US */
+	.strings		= composite_strings,
+};
+static struct usb_device_descriptor composite_device_desc = {
+	.bLength		= USB_DT_DEVICE_SIZE,
+	.bDescriptorType	= USB_DT_DEVICE,
+	.bcdUSB			= __constant_cpu_to_le16(0x0200),
+	.bDeviceClass		= USB_CLASS_PER_INTERFACE,
+	.bDeviceSubClass	= USB_CLASS_PER_INTERFACE,
+	.bDeviceProtocol	= 0,
+	.idVendor		= __constant_cpu_to_le16(VENDOR_ID),
+	.idProduct		= __constant_cpu_to_le16(PRODUCT_ID),
+	.iManufacturer		= COMPOSITE_MANUFACTURER_ID,
+	.iProduct		= COMPOSITE_PRODUCT_ID,
+	.iSerialNumber		= COMPOSITE_SERIALNUMBER_ID,
+	.bNumConfigurations	= NUM_CONFIGS,
+};
+static struct usb_config_descriptor composite_config_desc = {
+	.bLength		= USB_DT_CONFIG_SIZE,
+	.bDescriptorType	= USB_DT_CONFIG,
+	/* wTotalLenght computed dynamically */
+	.bNumInterfaces		= MAX_COMPOSITE_INTERFACES,
+	.bConfigurationValue	= COMPOSITE_CONFIG_NUMBER,
+	.iConfiguration		= COMPOSITE_CONFIG_SRT_ID,
+	.bmAttributes 		= USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+	.bMaxPower		= 1,
+};
+static struct usb_qualifier_descriptor composite_qualifier_desc = {
+	.bLength =		sizeof composite_qualifier_desc,
+	.bDescriptorType	= USB_DT_DEVICE_QUALIFIER,
+	.bcdUSB			= __constant_cpu_to_le16(0x0200),
+	.bDeviceClass		= USB_CLASS_PER_INTERFACE,
+	.bNumConfigurations	= NUM_CONFIGS,
+};
+
+struct usb_composite_dev        *cdev;
+
+/* Functions */
+
+/* module */
+static int __init composite_init(void);
+static void __exit composite_exit(void);
+
+/* usb_function register function */
+int usb_function_register(struct usb_function *);
+
+static int composite_func_bind(struct usb_composite_dev *composite_dev)
+{
+	struct usb_gadget *gadget = composite_dev->gadget;
+	cdev = composite_dev;
+
+	/* Code from serial gadget */
+	if (gadget->is_otg) {
+		composite_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+	}
+
+       cdev->config = composite_config_desc;
+       cdev->qual = composite_qualifier_desc;
+
+	/* Last str id in string usb of the composite */
+       cdev->next_string_id = COMPOSITE_CONFIG_SRT_ID;
+
+	snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+		init_utsname()->sysname, init_utsname()->release,
+		driver_desc);
+
+	return 0;
+}
+
+static struct usb_composite_driver composite_drv = {
+	.dev			= &composite_device_desc,
+	.strings		= &composite_stringtable,
+	.bind			= composite_func_bind,
+/*	.unbind			= ..., Do we need to code this? */
+/*	.setup			= ..., Same as above */
+	.functions		= LIST_HEAD_INIT(composite_drv.functions),
+};
+
+static int reset_interf_functions(void)
+{
+	int status = 0;
+	struct usb_function *f;
+
+	list_for_each_entry (f, &cdev->driver->functions, function) {
+       		cdev->current_func = f;
+		usb_composite_reset_interface(cdev);
+
+		if (status)
+			goto fail;
+	}
+
+	return 0;
+
+fail:
+	return status;
+}
+
+static int set_interf_functions(void)
+{
+	int status = 0;
+	struct usb_function *f;
+
+	cdev->next_interface_id = 0;
+
+	list_for_each_entry (f, &cdev->driver->functions, function) {
+		cdev->current_func = f;
+		status = usb_composite_interface_id(cdev);
+
+		if (status)
+			goto fail;
+	}
+	cdev->config.bNumInterfaces = cdev->next_interface_id;
+	return 0;
+fail:
+	return status;
+}
+
+/* usb_function_register
+ *
+ * Get from usb function drivers their struct usb_function
+ * and assembles all of them into one struct usb_composite_driver
+ */
+int  usb_function_register(struct usb_function *g_func)
+{
+	struct usb_composite_driver *d = &composite_drv;
+	int status = 0;
+
+	if (!g_func->name)
+		g_func->name = "Composite Gadget";
+
+	cdev->current_func = g_func;
+	status = g_func->bind(cdev->gadget);
+
+	if (status < 0)
+		goto fail;
+
+	/* Set interface id */
+	status = usb_composite_interface_id(cdev);
+	if (status < 0)
+		goto fail_conf_id;
+
+	/* Set string id */
+	status = usb_composite_string_id(cdev);
+	if (status < 0)
+		goto fail_conf_id;
+
+        cdev->config.bNumInterfaces = cdev->next_interface_id;
+	cdev->current_func = NULL;
+
+	list_add_tail(&g_func->function, &d->functions);
+	printk(KERN_INFO "USB Function registered.\n");
+
+	return 0;
+
+fail_conf_id:
+	g_func->unbind(cdev->gadget);
+	cdev->current_func = NULL;
+
+fail:
+	return status;
+}
+EXPORT_SYMBOL(usb_function_register);
+
+void usb_function_unregister(struct usb_function *g_func)
+{
+	cdev->current_func = g_func;
+	g_func->unbind(cdev->gadget);
+
+	list_del(&g_func->function);
+
+	cdev->current_func = NULL;
+
+	if (reset_interf_functions()) {
+		printk(KERN_INFO "Reset functions error!!!.\n");
+	 } else {
+	 	set_interf_functions();
+	 }
+}
+EXPORT_SYMBOL(usb_function_unregister);
+
+/* usb_composite_ep_reset
+ *
+ * This functions reset the state of a single endpoint.
+ */
+int usb_composite_ep_reset (struct usb_ep *ep)
+{
+	if (!ep)
+		return -EINVAL;
+
+	ep->driver_data = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(usb_composite_ep_reset);
+
+/* composite_init
+ *
+ * Register as a USB Composite driver
+ *
+ * This function calls composite_function_register() to assemble
+ * composite_drv properly. After that it calls usb_composite_register()
+ * to register this device as a composite device.
+ */
+
+/* This function will register de composite driver */
+static int __init composite_init(void)
+{
+	int retval = 0;
+
+	retval = usb_composite_register(&composite_drv);
+
+	if (retval)
+		return -EINVAL;
+	else
+		return 0;
+}
+
+static void __exit composite_exit(void)
+{
+	usb_composite_unregister(&composite_drv);
+
+	printk(KERN_INFO "composite_exit: %s %s unloaded\n",
+		COMPOSITE_DESC, COMPOSITE_VERSION);
+}
+module_init(composite_init);
+module_exit(composite_exit);

--
Best Regards,

Felipe Balbi
[email protected]

Nokia Institute of Technology - INdT
Kernel Developers Team

+55 92 2126 1003


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.