aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_rndis.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
-rw-r--r--drivers/usb/gadget/f_rndis.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index c9966cc07d3a..95dae4c1ea40 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -4,6 +4,8 @@
4 * Copyright (C) 2003-2005,2008 David Brownell 4 * Copyright (C) 2003-2005,2008 David Brownell
5 * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger 5 * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
6 * Copyright (C) 2008 Nokia Corporation 6 * Copyright (C) 2008 Nokia Corporation
7 * Copyright (C) 2009 Samsung Electronics
8 * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
7 * 9 *
8 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 11 * 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 = {
149 .bDataInterface = 0x01, 151 .bDataInterface = 0x01,
150}; 152};
151 153
152static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { 154static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = {
153 .bLength = sizeof acm_descriptor, 155 .bLength = sizeof rndis_acm_descriptor,
154 .bDescriptorType = USB_DT_CS_INTERFACE, 156 .bDescriptorType = USB_DT_CS_INTERFACE,
155 .bDescriptorSubType = USB_CDC_ACM_TYPE, 157 .bDescriptorSubType = USB_CDC_ACM_TYPE,
156 158
@@ -179,6 +181,20 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = {
179 /* .iInterface = DYNAMIC */ 181 /* .iInterface = DYNAMIC */
180}; 182};
181 183
184
185static struct usb_interface_assoc_descriptor
186rndis_iad_descriptor = {
187 .bLength = sizeof rndis_iad_descriptor,
188 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
189
190 .bFirstInterface = 0, /* XXX, hardcoded */
191 .bInterfaceCount = 2, // control + data
192 .bFunctionClass = USB_CLASS_COMM,
193 .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET,
194 .bFunctionProtocol = USB_CDC_PROTO_NONE,
195 /* .iFunction = DYNAMIC */
196};
197
182/* full speed support: */ 198/* full speed support: */
183 199
184static struct usb_endpoint_descriptor fs_notify_desc __initdata = { 200static struct usb_endpoint_descriptor fs_notify_desc __initdata = {
@@ -208,11 +224,12 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = {
208}; 224};
209 225
210static struct usb_descriptor_header *eth_fs_function[] __initdata = { 226static struct usb_descriptor_header *eth_fs_function[] __initdata = {
227 (struct usb_descriptor_header *) &rndis_iad_descriptor,
211 /* control interface matches ACM, not Ethernet */ 228 /* control interface matches ACM, not Ethernet */
212 (struct usb_descriptor_header *) &rndis_control_intf, 229 (struct usb_descriptor_header *) &rndis_control_intf,
213 (struct usb_descriptor_header *) &header_desc, 230 (struct usb_descriptor_header *) &header_desc,
214 (struct usb_descriptor_header *) &call_mgmt_descriptor, 231 (struct usb_descriptor_header *) &call_mgmt_descriptor,
215 (struct usb_descriptor_header *) &acm_descriptor, 232 (struct usb_descriptor_header *) &rndis_acm_descriptor,
216 (struct usb_descriptor_header *) &rndis_union_desc, 233 (struct usb_descriptor_header *) &rndis_union_desc,
217 (struct usb_descriptor_header *) &fs_notify_desc, 234 (struct usb_descriptor_header *) &fs_notify_desc,
218 /* data interface has no altsetting */ 235 /* data interface has no altsetting */
@@ -252,11 +269,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = {
252}; 269};
253 270
254static struct usb_descriptor_header *eth_hs_function[] __initdata = { 271static struct usb_descriptor_header *eth_hs_function[] __initdata = {
272 (struct usb_descriptor_header *) &rndis_iad_descriptor,
255 /* control interface matches ACM, not Ethernet */ 273 /* control interface matches ACM, not Ethernet */
256 (struct usb_descriptor_header *) &rndis_control_intf, 274 (struct usb_descriptor_header *) &rndis_control_intf,
257 (struct usb_descriptor_header *) &header_desc, 275 (struct usb_descriptor_header *) &header_desc,
258 (struct usb_descriptor_header *) &call_mgmt_descriptor, 276 (struct usb_descriptor_header *) &call_mgmt_descriptor,
259 (struct usb_descriptor_header *) &acm_descriptor, 277 (struct usb_descriptor_header *) &rndis_acm_descriptor,
260 (struct usb_descriptor_header *) &rndis_union_desc, 278 (struct usb_descriptor_header *) &rndis_union_desc,
261 (struct usb_descriptor_header *) &hs_notify_desc, 279 (struct usb_descriptor_header *) &hs_notify_desc,
262 /* data interface has no altsetting */ 280 /* data interface has no altsetting */
@@ -271,6 +289,7 @@ static struct usb_descriptor_header *eth_hs_function[] __initdata = {
271static struct usb_string rndis_string_defs[] = { 289static struct usb_string rndis_string_defs[] = {
272 [0].s = "RNDIS Communications Control", 290 [0].s = "RNDIS Communications Control",
273 [1].s = "RNDIS Ethernet Data", 291 [1].s = "RNDIS Ethernet Data",
292 [2].s = "RNDIS",
274 { } /* end of list */ 293 { } /* end of list */
275}; 294};
276 295
@@ -587,6 +606,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
587 if (status < 0) 606 if (status < 0)
588 goto fail; 607 goto fail;
589 rndis->ctrl_id = status; 608 rndis->ctrl_id = status;
609 rndis_iad_descriptor.bFirstInterface = status;
590 610
591 rndis_control_intf.bInterfaceNumber = status; 611 rndis_control_intf.bInterfaceNumber = status;
592 rndis_union_desc.bMasterInterface0 = status; 612 rndis_union_desc.bMasterInterface0 = status;
@@ -798,6 +818,13 @@ int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
798 return status; 818 return status;
799 rndis_string_defs[1].id = status; 819 rndis_string_defs[1].id = status;
800 rndis_data_intf.iInterface = status; 820 rndis_data_intf.iInterface = status;
821
822 /* IAD iFunction label */
823 status = usb_string_id(c->cdev);
824 if (status < 0)
825 return status;
826 rndis_string_defs[2].id = status;
827 rndis_iad_descriptor.iFunction = status;
801 } 828 }
802 829
803 /* allocate and initialize one new instance */ 830 /* allocate and initialize one new instance */