usb: gadget: Add Interface Association Descriptor to ECM
authorPraveena Nadahally <praveen.nadahally@stericsson.com>
Wed, 25 Jan 2012 10:02:03 +0000 (11:02 +0100)
committerFelipe Balbi <balbi@ti.com>
Mon, 30 Jan 2012 09:17:26 +0000 (11:17 +0200)
Add IAD to bind the two interfaces of ECM so that it works properly
in composite gadget mode.

Signed-off-by: Thirupathi <thirupathi.chippakurthy@stericsson.com>
Signed-off-by: Praveena Nadahally <praveen.nadahally@stericsson.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/f_ecm.c

index 11c07cb7d3372b967725dbaf1c3d236193603433..30b908f2a53da7a42b285aad2311a249fda3b776 100644 (file)
@@ -97,6 +97,20 @@ static inline unsigned ecm_bitrate(struct usb_gadget *g)
 
 /* interface descriptor: */
 
+static struct usb_interface_assoc_descriptor
+ecm_iad_descriptor = {
+       .bLength =              sizeof ecm_iad_descriptor,
+       .bDescriptorType =      USB_DT_INTERFACE_ASSOCIATION,
+
+       /* .bFirstInterface =   DYNAMIC, */
+       .bInterfaceCount =      2,      /* control + data */
+       .bFunctionClass =       USB_CLASS_COMM,
+       .bFunctionSubClass =    USB_CDC_SUBCLASS_ETHERNET,
+       .bFunctionProtocol =    USB_CDC_PROTO_NONE,
+       /* .iFunction =         DYNAMIC */
+};
+
+
 static struct usb_interface_descriptor ecm_control_intf = {
        .bLength =              sizeof ecm_control_intf,
        .bDescriptorType =      USB_DT_INTERFACE,
@@ -199,6 +213,7 @@ static struct usb_endpoint_descriptor fs_ecm_out_desc = {
 
 static struct usb_descriptor_header *ecm_fs_function[] = {
        /* CDC ECM control descriptors */
+       (struct usb_descriptor_header *) &ecm_iad_descriptor,
        (struct usb_descriptor_header *) &ecm_control_intf,
        (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
@@ -247,6 +262,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc = {
 
 static struct usb_descriptor_header *ecm_hs_function[] = {
        /* CDC ECM control descriptors */
+       (struct usb_descriptor_header *) &ecm_iad_descriptor,
        (struct usb_descriptor_header *) &ecm_control_intf,
        (struct usb_descriptor_header *) &ecm_header_desc,
        (struct usb_descriptor_header *) &ecm_union_desc,
@@ -339,6 +355,7 @@ static struct usb_string ecm_string_defs[] = {
        [0].s = "CDC Ethernet Control Model (ECM)",
        [1].s = NULL /* DYNAMIC */,
        [2].s = "CDC Ethernet Data",
+       [3].s = "CDC ECM",
        {  } /* end of list */
 };
 
@@ -674,6 +691,7 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        if (status < 0)
                goto fail;
        ecm->ctrl_id = status;
+       ecm_iad_descriptor.bFirstInterface = status;
 
        ecm_control_intf.bInterfaceNumber = status;
        ecm_union_desc.bMasterInterface0 = status;
@@ -864,6 +882,13 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
                        return status;
                ecm_string_defs[1].id = status;
                ecm_desc.iMACAddress = status;
+
+               /* IAD label */
+               status = usb_string_id(c->cdev);
+               if (status < 0)
+                       return status;
+               ecm_string_defs[3].id = status;
+               ecm_iad_descriptor.iFunction = status;
        }
 
        /* allocate and initialize one new instance */