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: Bjørn Mork <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
24f06716cd
commit
6eddcb4c82
1 changed files with 12 additions and 2 deletions
|
@ -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)
|
||||||
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 @@ next_desc:
|
||||||
/* 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,
|
||||||
|
|
Reference in a new issue