MTP host fixes:

Add support for detecting android MTP devices
Fix problem reading data packet with header sent separately from payload.

Change-Id: I07b34af6783ebe2e63a317796ba0c8223df86edf
Signed-off-by: Mike Lockwood <lockwood@android.com>
diff --git a/media/mtp/MtpClient.cpp b/media/mtp/MtpClient.cpp
index 8d10c27..b53fe54 100644
--- a/media/mtp/MtpClient.cpp
+++ b/media/mtp/MtpClient.cpp
@@ -118,52 +118,66 @@
             {
                 LOGD("Found camera: \"%s\" \"%s\"\n", usb_device_get_manufacturer_name(device),
                         usb_device_get_product_name(device));
+            } else if (interface->bInterfaceClass == 0xFF &&
+                    interface->bInterfaceSubClass == 0xFF &&
+                    interface->bInterfaceProtocol == 0) {
+                char* interfaceName = usb_device_get_string(device, interface->iInterface);
+                if (!interfaceName || strcmp(interfaceName, "MTP"))
+                    continue;
+                // Looks like an android style MTP device
+                LOGD("Found MTP device: \"%s\" \"%s\"\n", usb_device_get_manufacturer_name(device),
+                        usb_device_get_product_name(device));
+            } else {
+                // not an MTP or PTP device
+                continue;
+            }
 
-                // interface should be followed by three endpoints
-                struct usb_endpoint_descriptor *ep;
-                struct usb_endpoint_descriptor *ep_in_desc = NULL;
-                struct usb_endpoint_descriptor *ep_out_desc = NULL;
-                struct usb_endpoint_descriptor *ep_intr_desc = NULL;
-                for (int i = 0; i < 3; i++) {
-                    ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
-                    if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
-                        LOGE("endpoints not found\n");
-                        return mDone;
-                    }
-                    if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
-                        if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-                            ep_in_desc = ep;
-                        else
-                            ep_out_desc = ep;
-                    } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
-                        ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
-                        ep_intr_desc = ep;
-                    }
-                }
-                if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
+            // if we got here, then we have a likely MTP or PTP device
+
+            // interface should be followed by three endpoints
+            struct usb_endpoint_descriptor *ep;
+            struct usb_endpoint_descriptor *ep_in_desc = NULL;
+            struct usb_endpoint_descriptor *ep_out_desc = NULL;
+            struct usb_endpoint_descriptor *ep_intr_desc = NULL;
+            for (int i = 0; i < 3; i++) {
+                ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
+                if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
                     LOGE("endpoints not found\n");
                     return mDone;
                 }
-
-                struct usb_endpoint *ep_in = usb_endpoint_open(device, ep_in_desc);
-                struct usb_endpoint *ep_out = usb_endpoint_open(device, ep_out_desc);
-                struct usb_endpoint *ep_intr = usb_endpoint_open(device, ep_intr_desc);
-
-                if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
-                    LOGE("usb_device_claim_interface failed\n");
-                    usb_endpoint_close(ep_in);
-                    usb_endpoint_close(ep_out);
-                    usb_endpoint_close(ep_intr);
-                    return mDone;
+                if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
+                    if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+                        ep_in_desc = ep;
+                    else
+                        ep_out_desc = ep;
+                } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
+                    ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
+                    ep_intr_desc = ep;
                 }
-
-                MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
-                            ep_in, ep_out, ep_intr);
-                mDeviceList.add(mtpDevice);
-                mtpDevice->initialize();
-                deviceAdded(mtpDevice);
+            }
+            if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
+                LOGE("endpoints not found\n");
                 return mDone;
             }
+
+            struct usb_endpoint *ep_in = usb_endpoint_open(device, ep_in_desc);
+            struct usb_endpoint *ep_out = usb_endpoint_open(device, ep_out_desc);
+            struct usb_endpoint *ep_intr = usb_endpoint_open(device, ep_intr_desc);
+
+            if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
+                LOGE("usb_device_claim_interface failed\n");
+                usb_endpoint_close(ep_in);
+                usb_endpoint_close(ep_out);
+                usb_endpoint_close(ep_intr);
+                return mDone;
+            }
+
+            MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
+                        ep_in, ep_out, ep_intr);
+            mDeviceList.add(mtpDevice);
+            mtpDevice->initialize();
+            deviceAdded(mtpDevice);
+            return mDone;
         }
     }
 
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 6f9ea24..ebe764a 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -372,7 +372,7 @@
 int MtpDataPacket::read(struct usb_endpoint *ep) {
     // first read the header
     int length = transfer(ep, mBuffer, mBufferSize);
-    if (length > MTP_CONTAINER_HEADER_SIZE) {
+    if (length >= MTP_CONTAINER_HEADER_SIZE) {
         // look at the length field to see if the data spans multiple packets
         uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
         while (totalLength > length) {