Scan all descriptors when checking for fastboot

For Linux, the USB code was only looking at the first
descriptor when searching for the fastboot interface
which caused some devices to not be found.

Also clarify some code by using the actual USB structures
instead of void or char pointers.

Change-Id: I9e4871c4d477ac10ba75bb17a955f176809af289
Signed-off-by: Patrick Tjin <pattjin@google.com>
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index a45f9f8..fabbd51 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -100,12 +100,12 @@
 
 static int check(void *_desc, int len, unsigned type, int size)
 {
-    unsigned char *desc = _desc;
+    struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)_desc;
 
     if(len < size) return -1;
-    if(desc[0] < size) return -1;
-    if(desc[0] > len) return -1;
-    if(desc[1] != type) return -1;
+    if(hdr->bLength < size) return -1;
+    if(hdr->bLength > len) return -1;
+    if(hdr->bDescriptorType != type) return -1;
 
     return 0;
 }
@@ -125,15 +125,15 @@
     unsigned i;
     unsigned e;
     
-    if(check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
+    if (check(ptr, len, USB_DT_DEVICE, USB_DT_DEVICE_SIZE))
         return -1;
-    dev = (void*) ptr;
+    dev = (struct usb_device_descriptor *)ptr;
     len -= dev->bLength;
     ptr += dev->bLength;
 
-    if(check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE))
+    if (check(ptr, len, USB_DT_CONFIG, USB_DT_CONFIG_SIZE))
         return -1;
-    cfg = (void*) ptr;
+    cfg = (struct usb_config_descriptor *)ptr;
     len -= cfg->bLength;
     ptr += cfg->bLength;
 
@@ -177,9 +177,19 @@
     }
 
     for(i = 0; i < cfg->bNumInterfaces; i++) {
-        if(check(ptr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE))
+
+        while (len > 0) {
+	        struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr;
+            if (check(hdr, len, USB_DT_INTERFACE, USB_DT_INTERFACE_SIZE) == 0)
+                break;
+            len -= hdr->bLength;
+            ptr += hdr->bLength;
+        }
+
+        if (len <= 0)
             return -1;
-        ifc = (void*) ptr;
+
+        ifc = (struct usb_interface_descriptor *)ptr;
         len -= ifc->bLength;
         ptr += ifc->bLength;
 
@@ -190,16 +200,25 @@
         info.ifc_protocol = ifc->bInterfaceProtocol;
 
         for(e = 0; e < ifc->bNumEndpoints; e++) {
-            if(check(ptr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE))
-                return -1;
-            ept = (void*) ptr;
+            while (len > 0) {
+	            struct usb_descriptor_header *hdr = (struct usb_descriptor_header *)ptr;
+                if (check(hdr, len, USB_DT_ENDPOINT, USB_DT_ENDPOINT_SIZE) == 0)
+                    break;
+                len -= hdr->bLength;
+                ptr += hdr->bLength;
+            }
+            if (len < 0) {
+                break;
+            }
+
+            ept = (struct usb_endpoint_descriptor *)ptr;
             len -= ept->bLength;
             ptr += ept->bLength;
 
-            if((ept->bmAttributes & 0x03) != 0x02)
+            if((ept->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
                 continue;
 
-            if(ept->bEndpointAddress & 0x80) {
+            if(ept->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
                 in = ept->bEndpointAddress;
             } else {
                 out = ept->bEndpointAddress;