]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/usb/qmi_wwan.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / drivers / net / usb / qmi_wwan.c
index 1ba1fdc34988e65cee56cb0c6c829e25ed0588dd..c54719984c4bdd0da0e36dd54ab1430708483b0b 100644 (file)
@@ -229,11 +229,11 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
        u8 *buf = intf->cur_altsetting->extra;
        int len = intf->cur_altsetting->extralen;
        struct usb_interface_descriptor *desc = &intf->cur_altsetting->desc;
-       struct usb_cdc_union_desc *cdc_union = NULL;
-       struct usb_cdc_ether_desc *cdc_ether = NULL;
-       u32 found = 0;
+       struct usb_cdc_union_desc *cdc_union;
+       struct usb_cdc_ether_desc *cdc_ether;
        struct usb_driver *driver = driver_of(intf);
        struct qmi_wwan_state *info = (void *)&dev->data;
+       struct usb_cdc_parsed_header hdr;
 
        BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) <
                      sizeof(struct qmi_wwan_state)));
@@ -243,63 +243,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
        info->data = intf;
 
        /* and a number of CDC descriptors */
-       while (len > 3) {
-               struct usb_descriptor_header *h = (void *)buf;
-
-               /* ignore any misplaced descriptors */
-               if (h->bDescriptorType != USB_DT_CS_INTERFACE)
-                       goto next_desc;
-
-               /* buf[2] is CDC descriptor subtype */
-               switch (buf[2]) {
-               case USB_CDC_HEADER_TYPE:
-                       if (found & 1 << USB_CDC_HEADER_TYPE) {
-                               dev_dbg(&intf->dev, "extra CDC header\n");
-                               goto err;
-                       }
-                       if (h->bLength != sizeof(struct usb_cdc_header_desc)) {
-                               dev_dbg(&intf->dev, "CDC header len %u\n",
-                                       h->bLength);
-                               goto err;
-                       }
-                       break;
-               case USB_CDC_UNION_TYPE:
-                       if (found & 1 << USB_CDC_UNION_TYPE) {
-                               dev_dbg(&intf->dev, "extra CDC union\n");
-                               goto err;
-                       }
-                       if (h->bLength != sizeof(struct usb_cdc_union_desc)) {
-                               dev_dbg(&intf->dev, "CDC union len %u\n",
-                                       h->bLength);
-                               goto err;
-                       }
-                       cdc_union = (struct usb_cdc_union_desc *)buf;
-                       break;
-               case USB_CDC_ETHERNET_TYPE:
-                       if (found & 1 << USB_CDC_ETHERNET_TYPE) {
-                               dev_dbg(&intf->dev, "extra CDC ether\n");
-                               goto err;
-                       }
-                       if (h->bLength != sizeof(struct usb_cdc_ether_desc)) {
-                               dev_dbg(&intf->dev, "CDC ether len %u\n",
-                                       h->bLength);
-                               goto err;
-                       }
-                       cdc_ether = (struct usb_cdc_ether_desc *)buf;
-                       break;
-               }
-
-               /* Remember which CDC functional descriptors we've seen.  Works
-                * for all types we care about, of which USB_CDC_ETHERNET_TYPE
-                * (0x0f) is the highest numbered
-                */
-               if (buf[2] < 32)
-                       found |= 1 << buf[2];
-
-next_desc:
-               len -= h->bLength;
-               buf += h->bLength;
-       }
+       cdc_parse_cdc_header(&hdr, intf, buf, len);
+       cdc_union = hdr.usb_cdc_union_desc;
+       cdc_ether = hdr.usb_cdc_ether_desc;
 
        /* Use separate control and data interfaces if we found a CDC Union */
        if (cdc_union) {