diff mbox

[net] cdc_ether: Ignore bogus union descriptor for RNDIS devices

Message ID 1335437703-6800-1-git-send-email-bjorn@mork.no
State Superseded, archived
Headers show

Commit Message

Bjørn Mork April 26, 2012, 10:55 a.m. UTC
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: Bjørn Mork <bjorn@mork.no>
---
Something like this, then?

This has only been build tested by me as I don't have any of the affected
devices.  It would be great if any of the reporters could verify that it
solves the problem.  I can provide prebuilt modules for Debian 3.2 based
kernels to simplify the testing (just rmmod and insmod - no need to build
or boot).  Send me an email if you want the module.

Sorry for the long delay in following up this.  I totally forgot about it.


Bjørn

 drivers/net/usb/cdc_ether.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

Comments

Oliver Neukum April 26, 2012, 11:56 a.m. UTC | #1
Am Donnerstag, 26. April 2012, 12:55:03 schrieb Bjørn Mork:
> 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.

Very good, except that this is a bit risky, because we may use
interface 0 without checking that it belongs to us. Could you
add a sanity check that the interface for which probe() is called
is really the control interface in case a workaround is used?

	Regards
		Oliver
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 90a3002..4ed5a38 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)
 	struct cdc_state		*info = (void *) &dev->data;
 	int				status;
 	int				rndis;
+	bool				android_rndis_quirk = false;
 	struct usb_driver		*driver = driver_of(intf);
 	struct usb_cdc_mdlm_desc	*desc = 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)
 					info->control,
 					info->u->bSlaveInterface0,
 					info->data);
+				/* fall back to hard-wiring for RNDIS */
+				if (rndis) {
+					android_rndis_quirk = true;
+					goto next_desc;
+				}
 				goto bad_desc;
 			}
 			if (info->control != intf) {
@@ -271,8 +277,12 @@  next_desc:
 	/* Microsoft ActiveSync based and some regular RNDIS devices lack the
 	 * CDC descriptors, so we'll hard-wire the interfaces and not check
 	 * 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->data = usb_ifnum_to_if(dev->udev, 1);
 		if (!info->control || !info->data) {