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 _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel