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>
This commit is contained in:
Mike Lockwood
2010-07-20 12:01:36 -04:00
parent 108505b30f
commit 3c51d6a9ef
2 changed files with 54 additions and 40 deletions

View File

@@ -118,52 +118,66 @@ bool MtpClient::usbDeviceAdded(const char *devname) {
{
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;
}
}

View File

@@ -372,7 +372,7 @@ int MtpDataPacket::writeDataHeader(int fd, uint32_t length) {
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) {