diff options
author | Ajay Jawade <ajay.jawade@stericsson.com> | 2011-02-28 16:22:51 +0530 |
---|---|---|
committer | Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | 2011-03-07 05:18:42 +0100 |
commit | 95ea65ed2ec267b5a7728c298c761ad89b3f3abb (patch) | |
tree | 7adc98a98774d2af92b9ef6b27c521e9276fda5d /drivers/usb | |
parent | 994f7cb6d11c02b0ff8b6f0aa47aa9527f1a31ea (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/Kconfig | 66 | ||||
-rw-r--r-- | drivers/usb/gadget/android.c | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/f_rndis.c | 124 |
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) |