[PATCH] Base work for composite gadget support.

Signed-off-by: Felipe Balbi <[EMAIL PROTECTED]>
Signed-off-by: Ragner Magalhaes <[EMAIL PROTECTED]>
---

Index: 2.6-dev/drivers/usb/gadget/Kconfig
===================================================================
--- 2.6-dev.orig/drivers/usb/gadget/Kconfig     2007-01-29
11:40:21.000000000 -0400
+++ 2.6-dev/drivers/usb/gadget/Kconfig  2007-01-29 11:42:00.000000000
-0400
@@ -282,6 +282,15 @@
 
 # this first set of drivers all depend on bulk-capable hardware.
 
+config USB_COMPOSITE
+       tristate "Composite Gadget Support"
+       depends on USB_GADGET
+       help
+          A composite gadget is a device with more than one
+          interface.
+
+          This module adds support for this kind of device.
+
 config USB_ZERO
        tristate "Gadget Zero (DEVELOPMENT)"
        depends on EXPERIMENTAL
Index: 2.6-dev/drivers/usb/gadget/Makefile
===================================================================
--- 2.6-dev.orig/drivers/usb/gadget/Makefile    2007-01-29
11:40:21.000000000 -0400
+++ 2.6-dev/drivers/usb/gadget/Makefile 2007-01-29 11:42:18.000000000
-0400
@@ -19,6 +19,8 @@
 gadgetfs-objs                  := inode.o
 g_file_storage-objs            := file_storage.o usbstring.o config.o \
                                        epautoconf.o
+g_composite-objs               := composite_functions.o composite.o \
+                                       usbstring.o config.o epautoconf.o
 
 ifeq ($(CONFIG_USB_ETH_RNDIS),y)
        g_ether-objs            += rndis.o
@@ -30,4 +32,4 @@
 obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
 obj-$(CONFIG_USB_G_SERIAL)     += g_serial.o
 obj-$(CONFIG_USB_MIDI_GADGET)  += g_midi.o
-
+obj-$(CONFIG_USB_COMPOSITE)    += g_composite.o
Index: 2.6-dev/drivers/usb/gadget/composite.c
===================================================================
--- 2.6-dev.orig/drivers/usb/gadget/composite.c 2007-01-29
11:39:35.000000000 -0400
+++ 2.6-dev/drivers/usb/gadget/composite.c      2007-01-29 11:42:29.000000000
-0400
@@ -1,6 +1,3 @@
-#define DEBUG 1
-// #define VERBOSE
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
@@ -22,9 +19,12 @@
 #include <asm/unaligned.h>
 
 #include <linux/usb_ch9.h>
+#include <linux/usb/cdc.h>
 #include <linux/usb_gadget.h>
 #include <linux/usb/composite.h>
 
+#define DEBUG 1
+#define VERBOSE 1
 
 #define xprintk(d,level,fmt,args...) \
        dev_printk(level , &(d)->gadget->dev , fmt , ## args)
@@ -51,10 +51,22 @@
 #define INFO(dev,fmt,args...) \
        xprintk(dev , KERN_INFO , fmt , ## args)
 
+/* Defines */
+#define DRIVER_DESC            "Composite Device"
+#define DRIVER_VERSION                 "v1.0-alfa"
+#define DRIVER_NAME            "composite"
+
+static const char driver_desc [] = DRIVER_DESC;
+static const char shortname [] = DRIVER_NAME;
+
 /*-------------------------------------------------------------------------*/
 
+#define NUM_CONFIGS            1
+#define COMPOSITE_CONFIG_VALUE  3      /* composite config */
+
 /* big enough to hold our biggest descriptor */
-#define USB_BUFSIZ     512
+#define USB_BUFSIZ     256
+
 
 
 static struct usb_composite_driver     *composite;
@@ -78,6 +90,7 @@
 }
 
 /*-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
 
 /* To simplify, we expect to have only ONE real configuration, working
the
  * same no matter what speed it connects with.  A given function may
expose
@@ -85,7 +98,7 @@
  * class and endpoint descriptors (as usual).
  */
 
-#define        CONFIG_NUMBER   1
+#define COMPOSITE_CONFIG_NUMBER        1
 
 static int
 config_buf(struct usb_composite_dev *cdev, void *buf, u8 type)
@@ -103,11 +116,12 @@
        } else
                hs = 0;
 
+
        /* write a config descriptor */
        *c = cdev->config;
        c->bLength = USB_DT_CONFIG_SIZE;
        c->bDescriptorType = type;
-       c->bConfigurationValue = CONFIG_NUMBER;
+       c->bConfigurationValue = COMPOSITE_CONFIG_NUMBER;
 
        /* REVISIT some configurations might need other descriptors,
         * independent of the interfaces they implement ... notably
@@ -139,13 +153,14 @@
 ) {
        struct usb_function             *f;
        int                             result;
-
        DBG(cdev, "reset config\n");
 
        req->bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD |
USB_RECIP_DEVICE;
        req->bRequest = USB_REQ_SET_CONFIGURATION;
+       req->wValue = COMPOSITE_CONFIG_VALUE;
 
        list_for_each_entry (f, &composite->functions, function) {
+              cdev->current_func = f;
                result = f->setup(cdev, req);
                if (result < 0)
                        DBG(cdev, "reset function %s --> %d\n",
@@ -157,7 +172,7 @@
 static int
 composite_set_config(struct usb_composite_dev *cdev, unsigned number)
 {
-       int                     result = 0, tmp;
+       int                     result = 0;
        struct usb_gadget       *gadget = cdev->gadget;
        struct usb_ctrlrequest  req;
 
@@ -176,18 +191,19 @@
        case 0:
                usb_gadget_vbus_draw(gadget, is_otg(gadget) ? 8 : 100);
                break;
-       case CONFIG_NUMBER:
+       case COMPOSITE_CONFIG_NUMBER:
                req.bRequestType = USB_DIR_OUT
                                | USB_TYPE_STANDARD
                                | USB_RECIP_INTERFACE;
                req.bRequest = USB_REQ_SET_INTERFACE;
-
+/* ragner comments
                for (tmp = 0; tmp < MAX_COMPOSITE_INTERFACES; tmp++) {
                        struct usb_function     *f =
cdev->interface[tmp];
 
                        if (!f)
                                continue;
                        req.wIndex = cpu_to_le16(tmp);
+                      cdev->current_func = f;
                        result = f->setup(cdev, &req);
                        if (result < 0) {
                                DBG(cdev, "interface %d/%s alt 0--> %d
\n",
@@ -196,12 +212,13 @@
                                return result;
                        }
                }
-
+*/
                cdev->config.bConfigurationValue = number;
                usb_gadget_vbus_draw(gadget, 2 *
cdev->config.bMaxPower);
                break;
        }
 
+
        INFO(cdev, "%s speed config #%d\n",
                ({ char *speed;
                switch (gadget->speed) {
@@ -217,39 +234,37 @@
 /*-------------------------------------------------------------------------*/
 
 static void
-composite_collect_langs(const struct usb_gadget_strings **sp, __le16
*buf)
+composite_collect_langs(struct usb_gadget_strings *sp, __le16 *buf)
 {
        const struct usb_gadget_strings *s;
        u16                             language;
        __le16                          *tmp;
 
-       while (*sp) {
-               s = *sp;
+       if(sp) {
+               s = sp;
                language = cpu_to_le16(s->language);
                for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) {
                        if (*tmp == language)
-                               goto repeat;
+                              return;
                }
                *tmp++ = language;
-repeat:
-               sp++;
        }
 }
 
 static int composite_check_string(
-       const struct usb_gadget_strings **sp,
+       struct usb_gadget_strings *sp,
        void                            *buf,
        u16                             language,
        int                             id
 )
 {
-       const struct usb_gadget_strings *s;
+       struct usb_gadget_strings *s;
        int                             value;
 
-       while (*sp) {
-               s = *sp++;
+       if(sp) {
+               s = sp;
                if (s->language != language)
-                       continue;
+                      return -EINVAL;
                value = usb_gadget_get_string(s, id, buf);
                if (value > 0)
                        return value;
@@ -265,9 +280,9 @@
        /* 0 == report all available language codes */
        if (id == 0) {
                struct usb_string_descriptor    *s = buf;
-               const struct usb_gadget_strings **sp;
+               struct usb_gadget_strings *sp;
 
-               memset(s, 0, 256);
+               memset(s, 0, USB_BUFSIZ);
                s->bDescriptorType = USB_DT_STRING;
 
                sp = composite->strings;
@@ -332,20 +347,26 @@
        u16                             w_index =
le16_to_cpu(ctrl->wIndex);
        u16                             w_value =
le16_to_cpu(ctrl->wValue);
        u16                             w_length =
le16_to_cpu(ctrl->wLength);
+       struct usb_function             *f;
+       int result;
 
        req->zero = 0;
        switch (ctrl->bRequest) {
 
        case USB_REQ_GET_DESCRIPTOR:
+              VDBG(cdev, "Get descriptor control req=%d \n", w_value >> 8);
                if (ctrl->bRequestType != USB_DIR_IN)
                        goto unknown;
                switch (w_value >> 8) {
 
                case USB_DT_DEVICE:
+              VDBG(cdev, "Get descriptor device\n");
                        value = min(w_length, (u16) sizeof cdev->dev);
                        memcpy(req->buf, &cdev->dev, value);
                        break;
+#ifdef CONFIG_USB_GADGET_DUALSPEED
                case USB_DT_DEVICE_QUALIFIER:
+              VDBG(cdev, "Get descriptor qualifier\n");
                        if (!is_dualspeed(gadget))
                                break;
                        value = min(w_length, (u16) sizeof cdev->qual);
@@ -353,11 +374,13 @@
                        break;
 
                case USB_DT_OTHER_SPEED_CONFIG:
+              VDBG(cdev, "Get descriptor speed config\n");
                        if (!is_dualspeed(gadget))
                                break;
                        // FALLTHROUGH
-
+#endif
                case USB_DT_CONFIG:
+              VDBG(cdev, "Get descriptor config\n");
                        /* one config ... so it must always be index 0
*/
                        if (w_value & 0xff)
                                break;
@@ -367,6 +390,7 @@
                                value = min(w_length, (u16) value);
                        break;
                case USB_DT_STRING:
+              VDBG(cdev, "Get descriptor string lang=%x id=%d\n", w_index,
w_value & 0xff);
                        value = composite_lookup_string(req->buf,
w_index,
                                                w_value & 0xff);
                        if (value >= 0)
@@ -377,6 +401,7 @@
 
        /* currently one config, two speeds */
        case USB_REQ_SET_CONFIGURATION:
+              VDBG(cdev, "Set configuration control req=%d\n", w_value);
                if (ctrl->bRequestType != 0)
                        goto unknown;
                if (gadget->a_hnp_support)
@@ -390,6 +415,7 @@
                spin_unlock(&cdev->lock);
                break;
        case USB_REQ_GET_CONFIGURATION:
+              VDBG(cdev, "Get configuration control req\n");
                if (ctrl->bRequestType != USB_DIR_IN)
                        goto unknown;
                *(u8 *)req->buf = cdev->config.bConfigurationValue;
@@ -398,6 +424,7 @@
 
        /* function drivers must handle get/set altsetting */
        case USB_REQ_SET_INTERFACE:
+              VDBG(cdev, "Set interface control req=%d\n", w_index);
                if (ctrl->bRequestType != USB_RECIP_INTERFACE)
                        goto unknown;
                if (!cdev->config.bConfigurationValue
@@ -405,10 +432,13 @@
                                || !cdev->interface[w_index])
                        break;
                spin_lock(&cdev->lock);
-               value = cdev->interface[w_index]->setup(cdev, ctrl);
+              cdev->current_func =  cdev->interface[w_index];
+               value = cdev->current_func->setup(cdev, ctrl);
                spin_unlock(&cdev->lock);
+              goto done;
                break;
        case USB_REQ_GET_INTERFACE:
+              VDBG(cdev, "Get interface control req=%d\n", w_index);
                if (ctrl->bRequestType !=(USB_DIR_IN|
USB_RECIP_INTERFACE))
                        goto unknown;
                if (!cdev->config.bConfigurationValue
@@ -417,13 +447,28 @@
                        break;
                spin_lock(&cdev->lock);
                /* function must set cdev->req->buf[0] */
-               value = cdev->interface[w_index]->setup(cdev, ctrl);
+              cdev->current_func =  cdev->interface[w_index];
+               value = cdev->current_func->setup(cdev, ctrl);
                spin_unlock(&cdev->lock);
                value = min(w_length, (u16) 1);
+              goto done;
                break;
        default:
+              VDBG(cdev, "Default control req=%d\n", ctrl->bRequest);
+                       /* FIXME - POG/GAMBI: For unknown CLASS_TYPE */
+               list_for_each_entry (f, &cdev->driver->functions, function) {
+                       cdev->current_func = f;
+                       result = f->setup(cdev, ctrl);
+                       if (result >= 0) {
+                              DBG(cdev, "Default control req ok\n");
+                               value = result;
+                      }else {
+                              DBG(cdev, "Default control req not\n");
+                      }
+               }
+              goto done;
 unknown:
-               VDBG(dev,
+               VDBG(cdev,
                        "unknown control req%02x.%02x v%04x i%04x l%d
\n",
                        ctrl->bRequestType, ctrl->bRequest,
                        w_value, w_index, w_length);
@@ -440,6 +485,7 @@
                        composite_setup_complete(gadget->ep0, req);
                }
        }
+ done:
 
        /* device either stalls (value < 0) or reports success */
        return value;
@@ -451,7 +497,6 @@
        struct usb_composite_dev        *cdev = get_gadget_data(gadget);
        unsigned long                   flags;
        struct usb_ctrlrequest  req;
-
        DBG(cdev, "disconnect\n");
 
        memset(&req, 0, sizeof req);
@@ -472,9 +517,10 @@
        DBG(cdev, "unbind\n");
 
        list_for_each_entry (f, &cdev->driver->functions, function) {
+              cdev->current_func = f;
                if (f->unbind)
                        f->unbind(cdev);
-               if (f == cdev->current_bind)
+               if (f == cdev->current_func)
                        break;
        }
        if (composite->unbind)
@@ -487,14 +533,14 @@
        set_gadget_data(gadget, NULL);
 }
 
-static int __init
+static int//__init
 composite_bind(struct usb_gadget *gadget)
 {
        struct usb_composite_dev        *cdev;
        struct usb_function             *f;
        int                             status = -ENOMEM;
 
-       cdev = kzalloc(sizeof *cdev, SLAB_KERNEL);
+       cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
        if (!cdev)
                return status;
 
@@ -519,6 +565,10 @@
 
        usb_gadget_set_selfpowered(gadget);
 
+       /* before composite->bind() */
+       cdev->next_string_id = 0;
+       cdev->next_interface_id = 0;
+
        /* mostly to assign strings for whole device, like serial
number,
         * but potentially also to update power state and consumption
etc
         */
@@ -541,7 +591,7 @@
         */
        usb_ep_autoconfig_reset(gadget);
        list_for_each_entry (f, &cdev->driver->functions, function) {
-               cdev->current_bind = f;
+               cdev->current_func = f;
                status = f->bind(cdev);
                if (status < 0)
                        goto fail;
@@ -552,7 +602,7 @@
                        goto fail;
                }
        }
-       cdev->current_bind = NULL;
+       cdev->current_func = NULL;
        cdev->config.bNumInterfaces = cdev->next_interface_id;
 
        /* REVISIT eventually we want e.g. RNDIS and non-RNDIS configs,
@@ -582,22 +632,120 @@
        return status;
 }
 
+/* FIXME
+ * Set the string id for each string in the current
+ * func referenced by current_func
+ */
 int usb_composite_string_id(struct usb_composite_dev *cdev)
 {
-       if (cdev->current_bind && cdev->next_string_id < 255)
-               return cdev->next_string_id++;
-       return -ENODEV;
+       struct usb_function             *f = cdev->current_func;
+       struct usb_string *src = f->strings->strings;
+
+       if (!cdev->current_func && cdev->next_string_id >= 255) {
+               return -ENODEV;
+       }
+
+       for (; src && src->s ; src++) {
+               (src)->id = cdev->next_string_id;
+               cdev->next_string_id ++;
+       }
+
+       return 0;
 }
 
+/* Set the interface id for each interface in the current
+ * func referenced by current_func
+ */
 int usb_composite_interface_id(struct usb_composite_dev *cdev)
 {
-       if (cdev->next_interface_id < MAX_COMPOSITE_INTERFACES
-                       && cdev->current_bind) {
-               cdev->interface[cdev->next_interface_id] =
cdev->current_bind;
-               return cdev->next_interface_id++;
-       }
-       return -ENODEV;
+       struct usb_function             *f = cdev->current_func;
+       struct usb_descriptor_header **src;
+       struct usb_interface_descriptor *interf_desc;
+       struct usb_cdc_header_desc *cdc_desc;
+       struct usb_cdc_union_desc *union_desc;
+
+       int                             hs;
+
+       if (!cdev->current_func && cdev->next_interface_id >=
MAX_COMPOSITE_INTERFACES ) {
+               printk(KERN_INFO "Max composite interfaces ...\n" );
+               return -ENODEV;
+       }
+
+       if (is_dualspeed(cdev->gadget)) {
+               hs = (cdev->gadget->speed == USB_SPEED_HIGH);
+               //if (type == USB_DT_OTHER_SPEED_CONFIG)
+               //      hs = !hs;
+       } else
+               hs = 0;
+
+       f->interface_shift = cdev->next_interface_id;
+
+       src = hs ? f->hs_descriptors : f->descriptors;
+       for (; 0 != *src; src++) {
+               if( (*src)->bDescriptorType == USB_DT_INTERFACE ) {
+                       /* FIXME */
+                       interf_desc = (struct usb_interface_descriptor *) 
(*src);
+                       interf_desc->bInterfaceNumber += f->interface_shift;
+                       if( (cdev->next_interface_id - 
interf_desc->bInterfaceNumber) < 0 )
{
+                               printk(KERN_INFO "Invalid interface number 
...!\n" );
+                               return -EINVAL;
+                       }
+                       if( cdev->next_interface_id >= MAX_COMPOSITE_INTERFACES 
) {
+                               printk(KERN_INFO "Max composite interfaces 
...\n" );
+                               return -EINVAL;
+                       }
+                       cdev->interface[cdev->next_interface_id] = f;
+                       cdev->next_interface_id = interf_desc->bInterfaceNumber 
+ 1;
+               } else if( (*src)->bDescriptorType == USB_DT_CS_INTERFACE ) {
+                       /* FIXME */
+                       cdc_desc = (struct usb_cdc_header_desc *) (*src);
+                       if( cdc_desc->bDescriptorSubType == USB_CDC_UNION_TYPE 
) {
+                               union_desc = (struct usb_cdc_union_desc *) 
(*src);
+                               union_desc->bMasterInterface0 += 
f->interface_shift;
+                               union_desc->bSlaveInterface0 += 
f->interface_shift;
+                       }
+               }
+       }
+
+       return 0;
+}
+/* FIXME
+int composite_reset_interface_id(struct usb_composite_dev *cdev)
+{
+       struct usb_function             *f = cdev->current_func;
+       struct usb_descriptor_header **src;
+       struct usb_interface_descriptor *interf_desc;
+       struct usb_cdc_header_desc *cdc_desc;
+       struct usb_cdc_union_desc *union_desc;
+
+       int                             hs;
+
+       if (is_dualspeed(cdev->gadget)) {
+               hs = (cdev->gadget->speed == USB_SPEED_HIGH);
+               //if (type == USB_DT_OTHER_SPEED_CONFIG)
+               //      hs = !hs;
+       } else
+               hs = 0;
+
+       src = hs ? f->hs_descriptors : f->descriptors;
+
+       for (; 0 != *src; src++) {
+               if( (*src)->bDescriptorType == USB_DT_INTERFACE ) {
+                       interf_desc = (struct usb_interface_descriptor *) 
(*src);
+                       interf_desc->bInterfaceNumber -= f->interface_shift;
+               } else if( (*src)->bDescriptorType == USB_DT_CS_INTERFACE ) {
+                       cdc_desc = (struct usb_cdc_header_desc *) (*src);
+                       if( cdc_desc->bDescriptorSubType == USB_CDC_UNION_TYPE 
) {
+                               union_desc = (struct usb_cdc_union_desc *) 
(*src);
+                               union_desc->bMasterInterface0 -= 
f->interface_shift;
+                               union_desc->bSlaveInterface0 -= 
f->interface_shift;
+                       }
+               }
+       }
+
+       return 0;
 }
+*/
 
 /*-------------------------------------------------------------------------*/
 
@@ -610,7 +758,8 @@
        DBG(cdev, "suspend\n");
        /* revisit -- iterate cdev->interface? */
        list_for_each_entry (f, &cdev->driver->functions, function) {
-               if (!f->suspend)
+               cdev->current_func = f;
+              if (!f->suspend)
                        continue;
                f->suspend(cdev);
        }
@@ -625,6 +774,7 @@
        DBG(cdev, "resume\n");
        /* revisit -- iterate cdev->interface? */
        list_for_each_entry (f, &cdev->driver->functions, function) {
+                       cdev->current_func = f;
                if (!f->resume)
                        continue;
                f->resume(cdev);
@@ -648,10 +798,11 @@
 
        .driver = {
                .owner          = THIS_MODULE,
+              .name            = (char *) shortname,
        },
 };
 
-int usb_composite_register(struct usb_composite_driver *d)
+int /*__init*/ usb_composite_register(struct usb_composite_driver *d)
 {
        struct usb_function     *f;
 
@@ -677,3 +828,7 @@
 
        return usb_gadget_register_driver(&composite_driver);
 }
+void __exit usb_composite_unregister(struct usb_composite_driver *d)
+{
+       usb_gadget_unregister_driver(&composite_driver);
+}
Index: 2.6-dev/drivers/usb/gadget/composite_functions.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ 2.6-dev/drivers/usb/gadget/composite_functions.c    2007-01-29
11:42:50.000000000 -0400
@@ -0,0 +1,265 @@
+/*
+ * g_omap_composite.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.
+ *
+ */
+
+/* MODULE INCLUDES */
+#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"
+
+/* Defines */
+#define DRIVER_DESC            "Composite Driver"
+#define DRIVER_VERSION                 "v1.0-alfa"
+#define DRIVER_NAME            "composite"
+
+static const char driver_desc [] = DRIVER_DESC;
+static const char shortname [] = DRIVER_NAME;
+
+/* descriptors that are built on-demand */
+static char manufacturer [50];
+static char product_desc [40] = DRIVER_DESC;
+static char serial_number [20] = {"INdT0"};
+
+/*-------------------------------------------------------------------------*/
+
+#define NUM_CONFIGS            1
+
+#define VENDOR_ID              0x0525 /* NetChip */
+#define PRODUCT_ID             0Xa4a6 /* Linux-USB Serial */
+//#define VENDOR_ID    0x1a0a  /* OTG test device IDs */
+//#define PRODUCT_ID   0xbadd
+#define COMPOSITE_CONFIG_NUMBER                1 // ether ok
+
+/* 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(DRIVER_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 Alfa" },
+       {  } /* 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)
+{
+       cdev = composite_dev;
+       // Last id + 1
+       cdev->next_string_id = COMPOSITE_CONFIG_SRT_ID + 1;
+
+       cdev->config = composite_config_desc;
+       cdev->qual = composite_qualifier_desc;
+
+       snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s",
+               init_utsname()->sysname, init_utsname()->release,
+               driver_desc);
+
+       return 0;
+}
+
+
+/* Composite Driver Struct */
+
+static struct usb_composite_driver composite_drv = {
+       .dev                    = &composite_device_desc,
+       .strings                = &composite_stringtable,
+       .bind                   = composite_func_bind,
+//     .unbind                 = composite_unbind,
+//     .setup                  = composite_setup,
+       .functions              = LIST_HEAD_INIT(composite_drv.functions),
+};
+/* FIXME
+static int reset_functions() {
+       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;
+               composite_reset_interface_id(cdev);
+               status = usb_composite_interface_id(cdev);
+               if( status < 0 )
+                       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
+ */
+
+
+/* FIXME: Code this function properly */
+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;
+       printk(KERN_INFO "Set interface.\n");
+
+       // Set interface id
+       status = usb_composite_interface_id(cdev);
+       if(status)
+               goto fail;
+       /* FIXME
+       printk(KERN_INFO "Set string.\n");
+       status = usb_composite_string_id(cdev);
+       if(status)
+               goto fail;
+       */
+       status = g_func->bind(cdev);
+        cdev->config.bNumInterfaces = cdev->next_interface_id;
+       if( status < 0 )
+               goto fail;
+
+       list_add_tail(&g_func->function, &d->functions);
+       printk(KERN_INFO "USB Function registered.\n");
+       return 0;
+fail:
+       return status;
+}
+EXPORT_SYMBOL(usb_function_register);
+
+void usb_function_unregister(struct usb_function *g_func)
+{
+       //struct usb_composite_driver *d = &composite_drv;
+
+/* FIXME */
+       cdev->current_func = g_func;
+       g_func->unbind(cdev);
+       list_del(&g_func->function);//, &d->functions);
+/* FIXME
+ * How to do this???
+       if( reset_functions() < 0 )
+               printk(KERN_INFO "Reset functions error!!!.\n");
+*/
+}
+EXPORT_SYMBOL(usb_function_unregister);
+
+
+/*
+ * 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", DRIVER_DESC,
DRIVER_VERSION);
+}
+module_init(composite_init);
+module_exit(composite_exit);
Index: 2.6-dev/include/linux/usb/composite.h
===================================================================
--- 2.6-dev.orig/include/linux/usb/composite.h  2007-01-29
11:39:35.000000000 -0400
+++ 2.6-dev/include/linux/usb/composite.h       2007-01-29 11:43:16.000000000
-0400
@@ -40,9 +40,11 @@
  */
 struct usb_function {
        const char                              *name;
-       const struct usb_gadget_strings         **strings;
-       const struct usb_descriptor_header      **descriptors;
-       const struct usb_descriptor_header      **hs_descriptors;
+       struct usb_gadget_strings         *strings;
+       struct usb_descriptor_header      **descriptors;
+       struct usb_descriptor_header      **hs_descriptors;
+       void                                    *driver_data;   /* data
private to the driver */
+       u8                                      interface_shift;
 
        struct list_head                        function;
 
@@ -77,7 +79,7 @@
 struct usb_composite_driver {
        const char                              *name;
        const struct usb_device_descriptor      *dev;
-       const struct usb_gadget_strings         **strings;
+       struct usb_gadget_strings         *strings;
 
        /* REVISIT want a general "add more descriptors for config N"
         * hook; OTG would fall out naturally
@@ -95,6 +97,9 @@
 
 extern int usb_composite_register(struct usb_composite_driver *);
 
+extern void usb_composite_unregister(struct usb_composite_driver *);
+extern int usb_function_register(struct usb_function *);
+extern void usb_function_unregister(struct usb_function *);
 
 #define        MAX_COMPOSITE_INTERFACES                8       /* max
16 */
 
@@ -121,7 +126,7 @@
        /* INTERNALS -- not for function drivers */
        u8                      next_string_id;
        u8                      next_interface_id;
-       struct usb_function     *current_bind;
+       struct usb_function     *current_func;
        struct usb_function     *interface[MAX_COMPOSITE_INTERFACES];
 
        struct usb_composite_driver     *driver;
@@ -131,7 +136,12 @@
 /* IDs may be assigned ONLY during function driver bind() */
 extern int usb_composite_string_id(struct usb_composite_dev *c);
 extern int usb_composite_interface_id(struct usb_composite_dev *c);
+/* FIXME
+extern int composite_reset_interface_id(struct usb_composite_dev *c);
+*/
 
+
+extern int is_composite(void);
 #endif  /* __KERNEL__ */
 
 #endif /* __LINUX_USB_COMPOSITE_H */

-- 
Best Regards,

Felipe Balbi
[EMAIL PROTECTED]

Nokia Institute of Technology - INdT
Kernel Developers Team

+55 92 2126 1003


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to