aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
authorAjay Jawade <ajay.jawade@stericsson.com>2011-02-28 16:22:51 +0530
committerSrinidhi KASAGAR <srinidhi.kasagar@stericsson.com>2011-03-07 05:18:42 +0100
commit95ea65ed2ec267b5a7728c298c761ad89b3f3abb (patch)
tree7adc98a98774d2af92b9ef6b27c521e9276fda5d /drivers/usb
parent994f7cb6d11c02b0ff8b6f0aa47aa9527f1a31ea (diff)
[Android]: USB: Enable RNDIS
Enable RNDIS for Android Platform. Also provide the runtime configuration binding as Microsoft driver doesn't support the RNDIS in composite mode Also make the Class, SubClass and Protocol of IAD same as that of first interface as mentioned in the specification. ST-Ericsson ID: CR 272413 Change-Id: Ie39138a027b5162dd94482ffc664c6a40276b927 Signed-off-by: Ajay Jawade <ajay.jawade@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/17106 Reviewed-by: Praveena NADAHALLY <praveen.nadahally@stericsson.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/Kconfig66
-rw-r--r--drivers/usb/gadget/android.c4
-rw-r--r--drivers/usb/gadget/f_rndis.c124
3 files changed, 157 insertions, 37 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index f510dae8a65..70c5fe66931 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -856,12 +856,6 @@ config USB_ANDROID_ADB
help
Provides adb function for android gadget driver.
-config USB_ANDROID_ECM
- boolean "Android gadget ECM ether function"
- depends on USB_ANDROID
- help
- Provides ECM ether for android gadget driver.
-
config USB_ANDROID_MASS_STORAGE
boolean "Android gadget mass storage function"
depends on USB_ANDROID && SWITCH
@@ -874,21 +868,16 @@ config USB_ANDROID_MTP
help
Provides Media Transfer Protocol (MTP) support for android gadget driver.
-config USB_ANDROID_RNDIS
- boolean "Android gadget RNDIS ethernet function"
+config USB_ANDROID_ETHER
+ boolean "Android gadget Ethernet function"
depends on USB_ANDROID
help
- Provides RNDIS ethernet function for android gadget driver.
+ Provides CDC Ethernat (ECM: Ethernet Control Model) or
+ RNDIS (Remote NDIS) for android gadget driver.
-config USB_ANDROID_RNDIS_WCEIS
- boolean "Use Windows Internet Sharing Class/SubClass/Protocol"
- depends on USB_ANDROID_RNDIS
- help
- Causes the driver to look like a Windows-compatible Internet
- Sharing device, so Windows auto-detects it.
+ ECM: The drivers are not provided by Microsoft.
- If you enable this option, the device is no longer CDC ethernet
- compatible.
+ RNDIS: The drivers are provided by Microsoft.
config USB_CDC_COMPOSITE
tristate "CDC Composite Device (Ethernet and ACM)"
@@ -982,6 +971,48 @@ config USB_G_WEBCAM
endchoice
+choice
+ prompt "Ether Mode"
+ depends on USB_ANDROID_ETHER
+
+config USB_ANDROID_ECM
+ boolean "Android gadget ECM ether function"
+ depends on USB_ANDROID
+ help
+ Provides CDC Ethernet (ECM) ether for android gadget driver.
+
+ ECM and RNDIS should be mutually exclusive as both classes are
+ serving the same purpose.
+
+config USB_ANDROID_RNDIS
+ boolean "Android gadget RNDIS ethernet function"
+ depends on USB_ANDROID
+ help
+ Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol,
+ and Microsoft provides redistributable binary RNDIS drivers for
+ older versions of Windows.
+
+ If you say "y" here, the Ethernet gadget driver will try to provide
+ a second device configuration, supporting RNDIS to talk to such
+ Microsoft USB hosts.
+
+ To make MS-Windows work with this, use Documentation/usb/linux.inf
+ as the "driver info file". For versions of MS-Windows older than
+ XP, you'll need to download drivers from Microsoft's website; a URL
+ is given in comments found in that info file.
+
+config USB_ANDROID_RNDIS_WCEIS
+ boolean "Use Windows Internet Sharing Class/SubClass/Protocol"
+ depends on USB_ANDROID_RNDIS
+ help
+ Causes the driver to look like a Windows-compatible Internet
+ Sharing device, so Windows auto-detects it.
+
+ If you enable this option, the device is no longer CDC ethernet
+ compatible.
+
+endchoice
+
config USB_OTG_13
bool "OTG 1.3 USB SUPPORT"
select PM_RUNTIME
@@ -999,4 +1030,5 @@ config USB_OTG_20
help
Enabling the whitelist (Target Peripheral List-TPL) and runtime power
management at system level and usb level for OTG 2.0.
+
endif # USB_GADGET
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 7d0d93fd5ca..1b316f092bf 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -390,7 +390,9 @@ void android_enable_function(struct usb_function *f, int enable)
*/
list_for_each_entry(func, &android_config_driver.functions, list) {
if (!strcmp(func->name, "usb_mass_storage")
- || !strcmp(func->name, "mtp")) {
+ || !strcmp(func->name, "mtp")
+ || !strcmp(func->name, "adb")
+ || !strcmp(func->name, "acm")) {
usb_function_set_enabled(func, !enable);
}
}
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 2d9d97ecce2..6e6489b4958 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -198,9 +198,16 @@ rndis_iad_descriptor = {
.bFirstInterface = 0, /* XXX, hardcoded */
.bInterfaceCount = 2, // control + data
+#ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
+ /* "Wireless" RNDIS; auto-detected by Windows */
+ .bFunctionClass = USB_CLASS_WIRELESS_CONTROLLER,
+ .bFunctionSubClass = 1,
+ .bFunctionProtocol = 3,
+#else
.bFunctionClass = USB_CLASS_COMM,
- .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET,
- .bFunctionProtocol = USB_CDC_PROTO_NONE,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
+ .bFunctionProtocol = USB_CDC_ACM_PROTO_VENDOR,
+#endif
/* .iFunction = DYNAMIC */
};
@@ -602,6 +609,33 @@ static void rndis_close(struct gether *geth)
rndis_signal_disconnect(rndis->config);
}
+static rndis_release(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_rndis *rndis = func_to_rndis(f);
+ int status;
+ struct usb_ep *ep;
+
+ if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
+ if (rndis->notify_req) {
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+ }
+
+ /* we might as well release our claims on endpoints */
+ if (rndis->notify)
+ rndis->notify->driver_data = NULL;
+ if (rndis->port.out)
+ rndis->port.out_ep->driver_data = NULL;
+ if (rndis->port.in)
+ rndis->port.in_ep->driver_data = NULL;
+
+}
+
/*-------------------------------------------------------------------------*/
/* ethernet function driver setup/binding */
@@ -739,23 +773,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
- if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
- usb_free_descriptors(f->hs_descriptors);
- if (f->descriptors)
- usb_free_descriptors(f->descriptors);
-
- if (rndis->notify_req) {
- kfree(rndis->notify_req->buf);
- usb_ep_free_request(rndis->notify, rndis->notify_req);
- }
-
- /* we might as well release our claims on endpoints */
- if (rndis->notify)
- rndis->notify->driver_data = NULL;
- if (rndis->port.out)
- rndis->port.out_ep->driver_data = NULL;
- if (rndis->port.in)
- rndis->port.in_ep->driver_data = NULL;
+ rndis_release(c, f);
ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
@@ -912,9 +930,77 @@ int rndis_function_bind_config(struct usb_configuration *c)
return ret;
}
+static int rndis_function_rebind_config(struct usb_configuration *c,
+ struct usb_function *f)
+{
+
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_rndis *rndis = func_to_rndis(f);
+ int status1, status2 = 0;
+ struct usb_descriptor_header **desc = f->descriptors;
+
+ /* re-allocate instance-specific interface IDs */
+ status1 = usb_interface_id(c, f);
+
+ if (status1 < 0)
+ goto fail;
+ rndis->ctrl_id = status1;
+
+ rndis_iad_descriptor.bFirstInterface = status1;
+ rndis_control_intf.bInterfaceNumber = status1;
+ rndis_union_desc.bMasterInterface0 = status1;
+
+ ((struct usb_interface_assoc_descriptor *)desc[0])
+ ->bFirstInterface = status1;
+ ((struct usb_interface_descriptor *)desc[1])
+ ->bInterfaceNumber = status1;
+ ((struct usb_cdc_union_desc *)desc[5])
+ ->bMasterInterface0 = status1;
+
+ status2 = usb_interface_id(c, f);
+ if (status2 < 0)
+ goto fail;
+ rndis->data_id = status2;
+
+ rndis_data_intf.bInterfaceNumber = status2;
+ rndis_union_desc.bSlaveInterface0 = status2;
+
+ ((struct usb_interface_descriptor *)desc[7])
+ ->bInterfaceNumber = status2;
+ ((struct usb_cdc_union_desc *)desc[5])
+ ->bSlaveInterface0 = status2;
+
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ desc = f->hs_descriptors;
+ ((struct usb_interface_assoc_descriptor *)
+ desc[0])->bFirstInterface = status1;
+ ((struct usb_interface_descriptor *)
+ desc[1])->bInterfaceNumber = status1;
+ ((struct usb_cdc_union_desc *)
+ desc[3])->bMasterInterface0 = status1;
+
+ ((struct usb_interface_descriptor *)
+ desc[7])->bInterfaceNumber = status2;
+ ((struct usb_cdc_union_desc *)
+ desc[5])->bSlaveInterface0 = status2;
+ }
+
+ return 0;
+
+fail:
+ rndis_release(c, f);
+
+ ERROR(cdev, "%s: can't re-bind, err %d %d\n", f->name,
+ status1, status2);
+ if (status2 < 0)
+ status1 = status2;
+ return status1;
+}
+
static struct android_usb_function rndis_function = {
.name = "rndis",
.bind_config = rndis_function_bind_config,
+ .rebind_config = rndis_function_rebind_config,
};
static int __init init(void)