Commit 6eddcb4c authored by Bjørn Mork's avatar Bjørn Mork Committed by David S. Miller

cdc_ether: Ignore bogus union descriptor for RNDIS devices

Some RNDIS devices include a bogus CDC Union descriptor pointing
to non-existing interfaces.  The RNDIS code is already prepared
to handle devices without a CDC Union descriptor by hardwiring
the driver to use interfaces 0 and 1, which is correct for the
devices with the bogus descriptor as well. So we can reuse the
existing workaround.

Cc: Markus Kolb <linux-201011@tower-net.de>
Cc: Iker Salmón San Millán <shaola@esdebian.org>
Cc: Jonathan Nieder <jrnieder@gmail.com>
Cc: Oliver Neukum <oliver@neukum.org>
Cc: 655387@bugs.debian.org
Cc: stable@vger.kernel.org
Signed-off-by: default avatarBjørn Mork <bjorn@mork.no>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 24f06716
...@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
struct cdc_state *info = (void *) &dev->data; struct cdc_state *info = (void *) &dev->data;
int status; int status;
int rndis; int rndis;
bool android_rndis_quirk = false;
struct usb_driver *driver = driver_of(intf); struct usb_driver *driver = driver_of(intf);
struct usb_cdc_mdlm_desc *desc = NULL; struct usb_cdc_mdlm_desc *desc = NULL;
struct usb_cdc_mdlm_detail_desc *detail = NULL; 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,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
info->control, info->control,
info->u->bSlaveInterface0, info->u->bSlaveInterface0,
info->data); info->data);
/* fall back to hard-wiring for RNDIS */
if (rndis) {
android_rndis_quirk = true;
goto next_desc;
}
goto bad_desc; goto bad_desc;
} }
if (info->control != intf) { if (info->control != intf) {
...@@ -271,11 +277,15 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) ...@@ -271,11 +277,15 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
/* Microsoft ActiveSync based and some regular RNDIS devices lack the /* Microsoft ActiveSync based and some regular RNDIS devices lack the
* CDC descriptors, so we'll hard-wire the interfaces and not check * CDC descriptors, so we'll hard-wire the interfaces and not check
* for descriptors. * for descriptors.
*
* Some Android RNDIS devices have a CDC Union descriptor pointing
* to non-existing interfaces. Ignore that and attempt the same
* hard-wired 0 and 1 interfaces.
*/ */
if (rndis && !info->u) { if (rndis && (!info->u || android_rndis_quirk)) {
info->control = usb_ifnum_to_if(dev->udev, 0); info->control = usb_ifnum_to_if(dev->udev, 0);
info->data = usb_ifnum_to_if(dev->udev, 1); info->data = usb_ifnum_to_if(dev->udev, 1);
if (!info->control || !info->data) { if (!info->control || !info->data || info->control != intf) {
dev_dbg(&intf->dev, dev_dbg(&intf->dev,
"rndis: master #0/%p slave #1/%p\n", "rndis: master #0/%p slave #1/%p\n",
info->control, info->control,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment