diff options
Diffstat (limited to 'drivers/usb/gadget/f_rndis.c')
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index c9966cc07d3a..56b022150f22 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 |
@@ -22,6 +24,7 @@ | |||
22 | 24 | ||
23 | /* #define VERBOSE_DEBUG */ | 25 | /* #define VERBOSE_DEBUG */ |
24 | 26 | ||
27 | #include <linux/slab.h> | ||
25 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
26 | #include <linux/device.h> | 29 | #include <linux/device.h> |
27 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
@@ -149,8 +152,8 @@ static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { | |||
149 | .bDataInterface = 0x01, | 152 | .bDataInterface = 0x01, |
150 | }; | 153 | }; |
151 | 154 | ||
152 | static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { | 155 | static struct usb_cdc_acm_descriptor rndis_acm_descriptor __initdata = { |
153 | .bLength = sizeof acm_descriptor, | 156 | .bLength = sizeof rndis_acm_descriptor, |
154 | .bDescriptorType = USB_DT_CS_INTERFACE, | 157 | .bDescriptorType = USB_DT_CS_INTERFACE, |
155 | .bDescriptorSubType = USB_CDC_ACM_TYPE, | 158 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
156 | 159 | ||
@@ -179,6 +182,20 @@ static struct usb_interface_descriptor rndis_data_intf __initdata = { | |||
179 | /* .iInterface = DYNAMIC */ | 182 | /* .iInterface = DYNAMIC */ |
180 | }; | 183 | }; |
181 | 184 | ||
185 | |||
186 | static struct usb_interface_assoc_descriptor | ||
187 | rndis_iad_descriptor = { | ||
188 | .bLength = sizeof rndis_iad_descriptor, | ||
189 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | ||
190 | |||
191 | .bFirstInterface = 0, /* XXX, hardcoded */ | ||
192 | .bInterfaceCount = 2, // control + data | ||
193 | .bFunctionClass = USB_CLASS_COMM, | ||
194 | .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET, | ||
195 | .bFunctionProtocol = USB_CDC_PROTO_NONE, | ||
196 | /* .iFunction = DYNAMIC */ | ||
197 | }; | ||
198 | |||
182 | /* full speed support: */ | 199 | /* full speed support: */ |
183 | 200 | ||
184 | static struct usb_endpoint_descriptor fs_notify_desc __initdata = { | 201 | static struct usb_endpoint_descriptor fs_notify_desc __initdata = { |
@@ -208,11 +225,12 @@ static struct usb_endpoint_descriptor fs_out_desc __initdata = { | |||
208 | }; | 225 | }; |
209 | 226 | ||
210 | static struct usb_descriptor_header *eth_fs_function[] __initdata = { | 227 | static struct usb_descriptor_header *eth_fs_function[] __initdata = { |
228 | (struct usb_descriptor_header *) &rndis_iad_descriptor, | ||
211 | /* control interface matches ACM, not Ethernet */ | 229 | /* control interface matches ACM, not Ethernet */ |
212 | (struct usb_descriptor_header *) &rndis_control_intf, | 230 | (struct usb_descriptor_header *) &rndis_control_intf, |
213 | (struct usb_descriptor_header *) &header_desc, | 231 | (struct usb_descriptor_header *) &header_desc, |
214 | (struct usb_descriptor_header *) &call_mgmt_descriptor, | 232 | (struct usb_descriptor_header *) &call_mgmt_descriptor, |
215 | (struct usb_descriptor_header *) &acm_descriptor, | 233 | (struct usb_descriptor_header *) &rndis_acm_descriptor, |
216 | (struct usb_descriptor_header *) &rndis_union_desc, | 234 | (struct usb_descriptor_header *) &rndis_union_desc, |
217 | (struct usb_descriptor_header *) &fs_notify_desc, | 235 | (struct usb_descriptor_header *) &fs_notify_desc, |
218 | /* data interface has no altsetting */ | 236 | /* data interface has no altsetting */ |
@@ -252,11 +270,12 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { | |||
252 | }; | 270 | }; |
253 | 271 | ||
254 | static struct usb_descriptor_header *eth_hs_function[] __initdata = { | 272 | static struct usb_descriptor_header *eth_hs_function[] __initdata = { |
273 | (struct usb_descriptor_header *) &rndis_iad_descriptor, | ||
255 | /* control interface matches ACM, not Ethernet */ | 274 | /* control interface matches ACM, not Ethernet */ |
256 | (struct usb_descriptor_header *) &rndis_control_intf, | 275 | (struct usb_descriptor_header *) &rndis_control_intf, |
257 | (struct usb_descriptor_header *) &header_desc, | 276 | (struct usb_descriptor_header *) &header_desc, |
258 | (struct usb_descriptor_header *) &call_mgmt_descriptor, | 277 | (struct usb_descriptor_header *) &call_mgmt_descriptor, |
259 | (struct usb_descriptor_header *) &acm_descriptor, | 278 | (struct usb_descriptor_header *) &rndis_acm_descriptor, |
260 | (struct usb_descriptor_header *) &rndis_union_desc, | 279 | (struct usb_descriptor_header *) &rndis_union_desc, |
261 | (struct usb_descriptor_header *) &hs_notify_desc, | 280 | (struct usb_descriptor_header *) &hs_notify_desc, |
262 | /* data interface has no altsetting */ | 281 | /* data interface has no altsetting */ |
@@ -271,6 +290,7 @@ static struct usb_descriptor_header *eth_hs_function[] __initdata = { | |||
271 | static struct usb_string rndis_string_defs[] = { | 290 | static struct usb_string rndis_string_defs[] = { |
272 | [0].s = "RNDIS Communications Control", | 291 | [0].s = "RNDIS Communications Control", |
273 | [1].s = "RNDIS Ethernet Data", | 292 | [1].s = "RNDIS Ethernet Data", |
293 | [2].s = "RNDIS", | ||
274 | { } /* end of list */ | 294 | { } /* end of list */ |
275 | }; | 295 | }; |
276 | 296 | ||
@@ -587,6 +607,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
587 | if (status < 0) | 607 | if (status < 0) |
588 | goto fail; | 608 | goto fail; |
589 | rndis->ctrl_id = status; | 609 | rndis->ctrl_id = status; |
610 | rndis_iad_descriptor.bFirstInterface = status; | ||
590 | 611 | ||
591 | rndis_control_intf.bInterfaceNumber = status; | 612 | rndis_control_intf.bInterfaceNumber = status; |
592 | rndis_union_desc.bMasterInterface0 = status; | 613 | rndis_union_desc.bMasterInterface0 = status; |
@@ -749,10 +770,6 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f) | |||
749 | /* Some controllers can't support RNDIS ... */ | 770 | /* Some controllers can't support RNDIS ... */ |
750 | static inline bool can_support_rndis(struct usb_configuration *c) | 771 | static inline bool can_support_rndis(struct usb_configuration *c) |
751 | { | 772 | { |
752 | /* only two endpoints on sa1100 */ | ||
753 | if (gadget_is_sa1100(c->cdev->gadget)) | ||
754 | return false; | ||
755 | |||
756 | /* everything else is *presumably* fine */ | 773 | /* everything else is *presumably* fine */ |
757 | return true; | 774 | return true; |
758 | } | 775 | } |
@@ -798,6 +815,13 @@ int __init rndis_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) | |||
798 | return status; | 815 | return status; |
799 | rndis_string_defs[1].id = status; | 816 | rndis_string_defs[1].id = status; |
800 | rndis_data_intf.iInterface = status; | 817 | rndis_data_intf.iInterface = status; |
818 | |||
819 | /* IAD iFunction label */ | ||
820 | status = usb_string_id(c->cdev); | ||
821 | if (status < 0) | ||
822 | return status; | ||
823 | rndis_string_defs[2].id = status; | ||
824 | rndis_iad_descriptor.iFunction = status; | ||
801 | } | 825 | } |
802 | 826 | ||
803 | /* allocate and initialize one new instance */ | 827 | /* allocate and initialize one new instance */ |