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.c40
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
152static struct usb_cdc_acm_descriptor acm_descriptor __initdata = { 155static 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
186static struct usb_interface_assoc_descriptor
187rndis_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
184static struct usb_endpoint_descriptor fs_notify_desc __initdata = { 201static 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
210static struct usb_descriptor_header *eth_fs_function[] __initdata = { 227static 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
254static struct usb_descriptor_header *eth_hs_function[] __initdata = { 272static 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 = {
271static struct usb_string rndis_string_defs[] = { 290static 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 ... */
750static inline bool can_support_rndis(struct usb_configuration *c) 771static 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 */