diff options
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 35 |
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 | ||
152 | static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { | 154 | static 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 | |||
185 | static struct usb_interface_assoc_descriptor | ||
186 | rndis_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 | ||
184 | static struct usb_endpoint_descriptor fs_notify_desc __initdata = { | 200 | static 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 | ||
210 | static struct usb_descriptor_header *eth_fs_function[] __initdata = { | 226 | static 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 | ||
254 | static struct usb_descriptor_header *eth_hs_function[] __initdata = { | 271 | static 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 = { | |||
271 | static struct usb_string rndis_string_defs[] = { | 289 | static 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 */ |