- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / usb / gadget / f_rndis.c
index c9966cc..95dae4c 100644 (file)
@@ -4,6 +4,8 @@
  * Copyright (C) 2003-2005,2008 David Brownell
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2009 Samsung Electronics
+ *                    Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -149,8 +151,8 @@ static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = {
        .bDataInterface =       0x01,
 };
 
-static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
-       .bLength =              sizeof acm_descriptor,
+static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
+       .bLength =              sizeof rndis_acm_descriptor,
        .bDescriptorType =      USB_DT_CS_INTERFACE,
        .bDescriptorSubType =   USB_CDC_ACM_TYPE,
 
@@ -179,6 +181,20 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = {
        /* .iInterface = DYNAMIC */
 };
 
+
+static struct usb_interface_assoc_descriptor
+rndis_iad_descriptor = {
+       .bLength =              sizeof rndis_iad_descriptor,
+       .bDescriptorType =      USB_DT_INTERFACE_ASSOCIATION,
+
+       .bFirstInterface =      0, /* XXX, hardcoded */
+       .bInterfaceCount =      2,      // control + data
+       .bFunctionClass =       USB_CLASS_COMM,
+       .bFunctionSubClass =    USB_CDC_SUBCLASS_ETHERNET,
+       .bFunctionProtocol =    USB_CDC_PROTO_NONE,
+       /* .iFunction = DYNAMIC */
+};
+
 /* full speed support: */
 
 static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
@@ -208,11 +224,12 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
 };
 
 static struct usb_descriptor_header *eth_fs_function[] __initdata = {
+       (struct usb_descriptor_header *) &rndis_iad_descriptor,
        /* control interface matches ACM, not Ethernet */
        (struct usb_descriptor_header *) &rndis_control_intf,
        (struct usb_descriptor_header *) &header_desc,
        (struct usb_descriptor_header *) &call_mgmt_descriptor,
-       (struct usb_descriptor_header *) &acm_descriptor,
+       (struct usb_descriptor_header *) &rndis_acm_descriptor,
        (struct usb_descriptor_header *) &rndis_union_desc,
        (struct usb_descriptor_header *) &fs_notify_desc,
        /* data interface has no altsetting */
@@ -252,11 +269,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
 };
 
 static struct usb_descriptor_header *eth_hs_function[] __initdata = {
+       (struct usb_descriptor_header *) &rndis_iad_descriptor,
        /* control interface matches ACM, not Ethernet */
        (struct usb_descriptor_header *) &rndis_control_intf,
        (struct usb_descriptor_header *) &header_desc,
        (struct usb_descriptor_header *) &call_mgmt_descriptor,
-       (struct usb_descriptor_header *) &acm_descriptor,
+       (struct usb_descriptor_header *) &rndis_acm_descriptor,
        (struct usb_descriptor_header *) &rndis_union_desc,
        (struct usb_descriptor_header *) &hs_notify_desc,
        /* data interface has no altsetting */
@@ -271,6 +289,7 @@ static struct usb_descriptor_header *eth_hs_function[] __initdata = {
 static struct usb_string rndis_string_defs[] = {
        [0].s = "RNDIS Communications Control",
        [1].s = "RNDIS Ethernet Data",
+       [2].s = "RNDIS",
        {  } /* end of list */
 };
 
@@ -587,6 +606,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
        if (status < 0)
                goto fail;
        rndis->ctrl_id = status;
+       rndis_iad_descriptor.bFirstInterface = status;
 
        rndis_control_intf.bInterfaceNumber = status;
        rndis_union_desc.bMasterInterface0 = status;
@@ -798,6 +818,13 @@ int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
                        return status;
                rndis_string_defs[1].id = status;
                rndis_data_intf.iInterface = status;
+
+               /* IAD iFunction label */
+               status = usb_string_id(c->cdev);
+               if (status < 0)
+                       return status;
+               rndis_string_defs[2].id = status;
+               rndis_iad_descriptor.iFunction = status;
        }
 
        /* allocate and initialize one new instance */