diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/usb/cdc_ether.c | 14 |
1 files changed, 12 insertions, 2 deletions
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 90a30026a931..00880edba048 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c | |||
@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) | |||
83 | struct cdc_state *info = (void *) &dev->data; | 83 | struct cdc_state *info = (void *) &dev->data; |
84 | int status; | 84 | int status; |
85 | int rndis; | 85 | int rndis; |
86 | bool android_rndis_quirk = false; | ||
86 | struct usb_driver *driver = driver_of(intf); | 87 | struct usb_driver *driver = driver_of(intf); |
87 | struct usb_cdc_mdlm_desc *desc = NULL; | 88 | struct usb_cdc_mdlm_desc *desc = NULL; |
88 | struct usb_cdc_mdlm_detail_desc *detail = NULL; | 89 | struct usb_cdc_mdlm_detail_desc *detail = NULL; |
@@ -195,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) | |||
195 | info->control, | 196 | info->control, |
196 | info->u->bSlaveInterface0, | 197 | info->u->bSlaveInterface0, |
197 | info->data); | 198 | info->data); |
199 | /* fall back to hard-wiring for RNDIS */ | ||
200 | if (rndis) { | ||
201 | android_rndis_quirk = true; | ||
202 | goto next_desc; | ||
203 | } | ||
198 | goto bad_desc; | 204 | goto bad_desc; |
199 | } | 205 | } |
200 | if (info->control != intf) { | 206 | if (info->control != intf) { |
@@ -271,11 +277,15 @@ next_desc: | |||
271 | /* Microsoft ActiveSync based and some regular RNDIS devices lack the | 277 | /* Microsoft ActiveSync based and some regular RNDIS devices lack the |
272 | * CDC descriptors, so we'll hard-wire the interfaces and not check | 278 | * CDC descriptors, so we'll hard-wire the interfaces and not check |
273 | * for descriptors. | 279 | * for descriptors. |
280 | * | ||
281 | * Some Android RNDIS devices have a CDC Union descriptor pointing | ||
282 | * to non-existing interfaces. Ignore that and attempt the same | ||
283 | * hard-wired 0 and 1 interfaces. | ||
274 | */ | 284 | */ |
275 | if (rndis && !info->u) { | 285 | if (rndis && (!info->u || android_rndis_quirk)) { |
276 | info->control = usb_ifnum_to_if(dev->udev, 0); | 286 | info->control = usb_ifnum_to_if(dev->udev, 0); |
277 | info->data = usb_ifnum_to_if(dev->udev, 1); | 287 | info->data = usb_ifnum_to_if(dev->udev, 1); |
278 | if (!info->control || !info->data) { | 288 | if (!info->control || !info->data || info->control != intf) { |
279 | dev_dbg(&intf->dev, | 289 | dev_dbg(&intf->dev, |
280 | "rndis: master #0/%p slave #1/%p\n", | 290 | "rndis: master #0/%p slave #1/%p\n", |
281 | info->control, | 291 | info->control, |