]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/gadget/f_acm.c
USB: Interface Association Descriptors added to CDC & RNDIS
[net-next-2.6.git] / drivers / usb / gadget / f_acm.c
index 4e3657808b0f49fd245ac08d973975716827dd75..d10353d46b8604f927e4e051e61ff159932c2cc9 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
  * Copyright (C) 2008 by David Brownell
  * Copyright (C) 2008 by Nokia Corporation
+ * Copyright (C) 2009 by Samsung Electronics
+ * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
  *
  * This software is distributed under the terms of the GNU General
  * Public License ("GPL") as published by the Free Software Foundation,
@@ -99,6 +101,20 @@ static inline struct f_acm *port_to_acm(struct gserial *p)
 
 /* interface and class descriptors: */
 
+static struct usb_interface_assoc_descriptor
+acm_iad_descriptor = {
+       .bLength =              sizeof acm_iad_descriptor,
+       .bDescriptorType =      USB_DT_INTERFACE_ASSOCIATION,
+
+       /* .bFirstInterface =   DYNAMIC, */
+       .bInterfaceCount =      2,      // control + data
+       .bFunctionClass =       USB_CLASS_COMM,
+       .bFunctionSubClass =    USB_CDC_SUBCLASS_ACM,
+       .bFunctionProtocol =    USB_CDC_PROTO_NONE,
+       /* .iFunction =         DYNAMIC */
+};
+
+
 static struct usb_interface_descriptor acm_control_interface_desc __initdata = {
        .bLength =              USB_DT_INTERFACE_SIZE,
        .bDescriptorType =      USB_DT_INTERFACE,
@@ -178,6 +194,7 @@ static struct usb_endpoint_descriptor acm_fs_out_desc __initdata = {
 };
 
 static struct usb_descriptor_header *acm_fs_function[] __initdata = {
+       (struct usb_descriptor_header *) &acm_iad_descriptor,
        (struct usb_descriptor_header *) &acm_control_interface_desc,
        (struct usb_descriptor_header *) &acm_header_desc,
        (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
@@ -216,6 +233,7 @@ static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = {
 };
 
 static struct usb_descriptor_header *acm_hs_function[] __initdata = {
+       (struct usb_descriptor_header *) &acm_iad_descriptor,
        (struct usb_descriptor_header *) &acm_control_interface_desc,
        (struct usb_descriptor_header *) &acm_header_desc,
        (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
@@ -232,11 +250,13 @@ static struct usb_descriptor_header *acm_hs_function[] __initdata = {
 
 #define ACM_CTRL_IDX   0
 #define ACM_DATA_IDX   1
+#define ACM_IAD_IDX    2
 
 /* static strings, in UTF-8 */
 static struct usb_string acm_string_defs[] = {
        [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
        [ACM_DATA_IDX].s = "CDC ACM Data",
+       [ACM_IAD_IDX ].s = "CDC Serial",
        {  /* ZEROES END LIST */ },
 };
 
@@ -563,6 +583,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        if (status < 0)
                goto fail;
        acm->ctrl_id = status;
+       acm_iad_descriptor.bFirstInterface = status;
 
        acm_control_interface_desc.bInterfaceNumber = status;
        acm_union_desc .bMasterInterface0 = status;
@@ -732,6 +753,13 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
                acm_string_defs[ACM_DATA_IDX].id = status;
 
                acm_data_interface_desc.iInterface = status;
+
+               status = usb_string_id(c->cdev);
+               if (status < 0)
+                       return status;
+               acm_string_defs[ACM_IAD_IDX].id = status;
+
+               acm_iad_descriptor.iFunction = status;
        }
 
        /* allocate and initialize one new instance */