net: cdc_ncm: only the control intf can be probed
[deliverable/linux.git] / drivers / net / usb / cdc_ncm.c
index 4de3a5423e875567bf656702d7e15f99fa55b3b8..5aa3e60851d0f76a0092c6edba9f7e3ff91ce9e7 100644 (file)
@@ -280,6 +280,7 @@ static u8 cdc_ncm_setup(struct usbnet *dev)
                        /* if value changed, update device */
                        if (ctx->max_datagram_size !=
                                        le16_to_cpu(max_datagram_size)) {
+                               max_datagram_size = cpu_to_le16(ctx->max_datagram_size);
                                err = usbnet_write_cmd(dev,
                                                USB_CDC_SET_MAX_DATAGRAM_SIZE,
                                                USB_TYPE_CLASS | USB_DIR_OUT
@@ -371,6 +372,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
 
 int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
 {
+       const struct usb_cdc_union_desc *union_desc = NULL;
        struct cdc_ncm_ctx *ctx;
        struct usb_driver *driver;
        u8 *buf;
@@ -392,6 +394,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
        /* store ctx pointer in device data field */
        dev->data[0] = (unsigned long)ctx;
 
+       /* only the control interface can be successfully probed */
+       ctx->control = intf;
+
        /* get some pointers */
        driver = driver_of(intf);
        buf = intf->cur_altsetting->extra;
@@ -405,16 +410,16 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
 
                switch (buf[2]) {
                case USB_CDC_UNION_TYPE:
-                       if (buf[0] < sizeof(*(ctx->union_desc)))
+                       if (buf[0] < sizeof(*union_desc))
                                break;
 
-                       ctx->union_desc =
-                                       (const struct usb_cdc_union_desc *)buf;
-
-                       ctx->control = usb_ifnum_to_if(dev->udev,
-                                       ctx->union_desc->bMasterInterface0);
+                       union_desc = (const struct usb_cdc_union_desc *)buf;
+                       /* the master must be the interface we are probing */
+                       if (intf->cur_altsetting->desc.bInterfaceNumber !=
+                           union_desc->bMasterInterface0)
+                               goto error;
                        ctx->data = usb_ifnum_to_if(dev->udev,
-                                       ctx->union_desc->bSlaveInterface0);
+                                                   union_desc->bSlaveInterface0);
                        break;
 
                case USB_CDC_ETHERNET_TYPE:
@@ -457,15 +462,13 @@ advance:
        }
 
        /* some buggy devices have an IAD but no CDC Union */
-       if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
-               ctx->control = intf;
+       if (!union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
                ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1);
                dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n");
        }
 
        /* check if we got everything */
-       if ((ctx->control == NULL) || (ctx->data == NULL) ||
-           ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
+       if (!ctx->data || (!ctx->mbim_desc && !ctx->ether_desc))
                goto error;
 
        /* claim data interface, if different from control */
This page took 0.030051 seconds and 5 git commands to generate.