MtpDevice.cpp revision 8023f3af62795b7816f36a9423f8e0a39e616e49
15ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood/* 25ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 35ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * 45ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 55ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * you may not use this file except in compliance with the License. 65ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * You may obtain a copy of the License at 75ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * 85ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 95ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * 105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * Unless required by applicable law or agreed to in writing, software 115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * See the License for the specific language governing permissions and 145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood * limitations under the License. 155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood */ 165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 17a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood#define LOG_TAG "MtpDevice" 18b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood 19b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDebug.h" 20b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDevice.h" 21b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDeviceInfo.h" 22b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpObjectInfo.h" 23b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpProperty.h" 24b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStorageInfo.h" 25b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStringBuffer.h" 260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include "MtpUtils.h" 27a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdio.h> 295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdlib.h> 305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/types.h> 315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/ioctl.h> 325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/stat.h> 335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <fcntl.h> 345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <errno.h> 350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include <endian.h> 365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <usbhost/usbhost.h> 385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodnamespace android { 405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 41d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0 4223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodstatic bool isMtpDevice(uint16_t vendor, uint16_t product) { 4323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Sandisk Sansa Fuze 4423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (vendor == 0x0781 && product == 0x74c2) 4523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return true; 4623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Samsung YP-Z5 4723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (vendor == 0x04e8 && product == 0x503c) 4823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return true; 4923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return false; 5023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 51d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif 5223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 5323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike LockwoodMtpDevice* MtpDevice::open(const char* deviceName, int fd) { 5423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_device *device = usb_device_new(deviceName, fd); 5523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!device) { 5629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("usb_device_new failed for %s", deviceName); 5723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 5823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 5923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 6023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_descriptor_header* desc; 6123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_descriptor_iter iter; 6223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 6323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood usb_descriptor_iter_init(device, &iter); 6423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 6523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood while ((desc = usb_descriptor_iter_next(&iter)) != NULL) { 6623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (desc->bDescriptorType == USB_DT_INTERFACE) { 6723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc; 6823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 6923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE && 7023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceSubClass == 1 && // Still Image Capture 7123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceProtocol == 1) // Picture Transfer Protocol (PIMA 15470) 7223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood { 7331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* manufacturerName = usb_device_get_manufacturer_name(device); 7431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* productName = usb_device_get_product_name(device); 75b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName); 7631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(manufacturerName); 7731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(productName); 7823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else if (interface->bInterfaceClass == 0xFF && 7923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceSubClass == 0xFF && 8023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceProtocol == 0) { 8123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char* interfaceName = usb_device_get_string(device, interface->iInterface); 8231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (!interfaceName) { 8323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood continue; 8431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else if (strcmp(interfaceName, "MTP")) { 8531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(interfaceName); 8631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root continue; 8731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 8831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(interfaceName); 8931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root 9023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Looks like an android style MTP device 9131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* manufacturerName = usb_device_get_manufacturer_name(device); 9231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* productName = usb_device_get_product_name(device); 93b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName); 9431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(manufacturerName); 9531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(productName); 96d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood } 97d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0 98d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood else { 9923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // look for special cased devices based on vendor/product ID 10023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // we are doing this mainly for testing purposes 10123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint16_t vendor = usb_device_get_vendor_id(device); 10223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint16_t product = usb_device_get_product_id(device); 10323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!isMtpDevice(vendor, product)) { 10423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // not an MTP or PTP device 10523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood continue; 10623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 10723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // request MTP OS string and descriptor 10823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // some music players need to see this before entering MTP mode. 10923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char buffer[256]; 11023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood memset(buffer, 0, sizeof(buffer)); 111f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood int ret = usb_device_control_transfer(device, 11223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD, 11323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE, 114f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood 0, buffer, sizeof(buffer), 0); 115f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno); 11623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ret > 0) { 11723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("got MTP string %s\n", buffer); 118f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood ret = usb_device_control_transfer(device, 11923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1, 120f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood 0, 4, buffer, sizeof(buffer), 0); 12123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("OS descriptor got %d\n", ret); 12223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 12323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("no MTP string\n"); 12423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 12523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 126d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif 12723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // if we got here, then we have a likely MTP or PTP device 12823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 12923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // interface should be followed by three endpoints 13023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep; 13123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_in_desc = NULL; 13223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_out_desc = NULL; 13323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_intr_desc = NULL; 1348023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor; 1358023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL; 13623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood for (int i = 0; i < 3; i++) { 13723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter); 1388023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) { 1398023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ALOGD("Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n"); 1408023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep; 1418023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter); 1428023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang } 1438023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang 14423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) { 14529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 14631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 14723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 14823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 1498023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang 15023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { 15123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 15223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc = ep; 15323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood else 15423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_out_desc = ep; 15523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT && 15623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 15723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_intr_desc = ep; 15823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 15923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 16023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) { 16129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 16231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 16323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 16423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 16523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 16623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (usb_device_claim_interface(device, interface->bInterfaceNumber)) { 16729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("usb_device_claim_interface failed errno: %d\n", errno); 16831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 16923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 17023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 17123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 17223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber, 17323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc, ep_out_desc, ep_intr_desc); 17423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mtpDevice->initialize(); 17523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return mtpDevice; 17623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 17723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 17823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 17923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood usb_device_close(device); 18029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("device not found"); 18123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 18223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 18323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 1845ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface, 18542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_in, 18642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_out, 18742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_intr) 1885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood : mDevice(device), 1895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mInterface(interface), 19042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1(NULL), 19142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2(NULL), 19242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut(NULL), 19342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr(NULL), 1945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo(NULL), 1955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID(0), 196f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mTransactionID(0), 197f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse(false) 1985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{ 19942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1 = usb_request_new(device, ep_in); 20042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2 = usb_request_new(device, ep_in); 20142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut = usb_request_new(device, ep_out); 20242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr = usb_request_new(device, ep_intr); 2035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2055ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() { 2065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood close(); 2073ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mDeviceProperties.size(); i++) 208a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood delete mDeviceProperties[i]; 20942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn1); 21042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn2); 21142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestOut); 21242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIntr); 2135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() { 2165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood openSession(); 2175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo = getDeviceInfo(); 2185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDeviceInfo) { 219a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (mDeviceInfo->mDeviceProperties) { 220a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 221a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood for (int i = 0; i < count; i++) { 222a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 223a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2240c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) 225a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mDeviceProperties.push(property); 226a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 227a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 2285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() { 2325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) { 2335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_release_interface(mDevice, mInterface); 2345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_close(mDevice); 2355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDevice = NULL; 2365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2390c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwoodvoid MtpDevice::print() { 2400c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo) { 2410c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood mDeviceInfo->print(); 2420c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2430c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mDeviceProperties) { 244df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** DEVICE PROPERTIES *****\n"); 2450c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 2460c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2470c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 2480c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2490c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) { 2500c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 25131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 2520c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2530c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2540c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2550c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2560c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2570c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mPlaybackFormats) { 258df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** OBJECT PROPERTIES *****\n"); 2590c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mPlaybackFormats->size(); 2600c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2610c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i]; 262df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format)); 2630c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectPropertyList* props = getObjectPropsSupported(format); 2640c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (props) { 2653ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t j = 0; j < props->size(); j++) { 2660c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectProperty prop = (*props)[j]; 26799e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood MtpProperty* property = getObjectPropDesc(prop, format); 26831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (property) { 2690c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 27031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 27131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 27229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("could not fetch property: %s", 2730c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDebug::getObjectPropCodeName(prop)); 27431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 2750c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2760c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2770c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2780c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2790c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood} 2800c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() { 2825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) 2835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return usb_device_get_name(mDevice); 2845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else 2855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return "???"; 2865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() { 2890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 2900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 2915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = 0; 2925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 0; 2935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpSessionID newSession = 1; 2945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 2955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, newSession); 2965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_OPEN_SESSION)) 2975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 2985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 2995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN) 3005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood newSession = mResponse.getParameter(1); 3015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else if (ret != MTP_RESPONSE_OK) 3025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 3035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = newSession; 3055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 1; 3065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 3075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() { 3105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood // FIXME 3115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 3125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3145ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() { 3150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO)) 3195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpDeviceInfo* info = new MtpDeviceInfo; 3255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3315ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() { 3320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS)) 3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) { 3470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO)) 3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpStorageInfo* info = new MtpStorageInfo(storageID); 3585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3645ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID, 3655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectFormat format, MtpObjectHandle parent) { 3660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(2, format); 3715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(3, parent); 3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES)) 3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) { 3840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3866afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood // FIXME - we might want to add some caching here 3876afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 3885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, handle); 3905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO)) 3915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectInfo* info = new MtpObjectInfo(handle); 3975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 4005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 4025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 4033e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) { 4040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4063e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.reset(); 4073e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.setParameter(1, handle); 4083e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) { 4093e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood MtpResponseCode ret = readResponse(); 4103e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4113e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return mData.getData(outLength); 4123e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4133e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4143e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood outLength = 0; 4153e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return NULL; 4166afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 4176afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) { 4190cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4200cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4220cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpObjectHandle parent = info->mParent; 4230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (parent == 0) 4240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood parent = MTP_PARENT_ROOT; 4250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mStorageID); 4270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(2, info->mParent); 4280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mStorageID); 4300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mFormat); 4310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mProtectionStatus); 4320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mCompressedSize); 4330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mThumbFormat); 4340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbCompressedSize); 4350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixWidth); 4360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixHeight); 4370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixWidth); 4380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixHeight); 4390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixDepth); 4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mParent); 4410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mAssociationType); 4420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mAssociationDesc); 4430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mSequenceNumber); 4440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mName); 4450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char created[100], modified[100]; 4470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateCreated, created, sizeof(created)); 4480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateModified, modified, sizeof(modified)); 4490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(created); 4510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(modified); 4520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (info->mKeywords) 4530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mKeywords); 4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood else 4550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putEmptyString(); 4560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 4580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mStorageID = mResponse.getParameter(1); 4610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mParent = mResponse.getParameter(2); 4620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mHandle = mResponse.getParameter(3); 4630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return info->mHandle; 4640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (MtpObjectHandle)-1; 4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) { 4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int remaining = info->mCompressedSize; 4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mHandle); 4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 4760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // send data header 4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining); 4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char buffer[65536]; 4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood while (remaining > 0) { 4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int count = read(srcFD, buffer, sizeof(buffer)); 4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (count > 0) { 48342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int written = mData.write(mRequestOut, buffer, count); 4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // FIXME check error 4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood remaining -= count; 4860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood break; 4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (remaining == 0 && ret == MTP_RESPONSE_OK); 4930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 4940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4956afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) { 4960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4986afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.reset(); 4996afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.setParameter(1, handle); 5006afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 5016afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpResponseCode ret = readResponse(); 5026afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (ret == MTP_RESPONSE_OK) 5036afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return true; 5046afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood } 5056afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return false; 5066afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5076afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 5086afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 5096afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 51031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 51131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle parent = info->mParent; 51231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 51331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return parent; 51431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5156afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 51631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5176afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5183e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 5196afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 5206afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 52131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 52231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle storageId = info->mStorageID; 52331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 52431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return storageId; 52531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5266afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 52731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5283e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood} 5293e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 53098693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 53198693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 53298693f674125484de8873d969c209276a6dd604bMike Lockwood 53398693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 53498693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, format); 53598693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 53698693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 53798693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 53898693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 53998693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 54098693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 54198693f674125484de8873d969c209276a6dd604bMike Lockwood return mData.getAUInt16(); 54298693f674125484de8873d969c209276a6dd604bMike Lockwood } 54398693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 54498693f674125484de8873d969c209276a6dd604bMike Lockwood 54598693f674125484de8873d969c209276a6dd604bMike Lockwood} 54698693f674125484de8873d969c209276a6dd604bMike Lockwood 547a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 5480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 550a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.reset(); 551a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.setParameter(1, code); 552a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 553a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 554a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!readData()) 555a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 556a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpResponseCode ret = readResponse(); 557a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (ret == MTP_RESPONSE_OK) { 558a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = new MtpProperty; 559e3e76c456baee122de6715ae280130abaddc906cMike Lockwood property->read(mData); 560a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return property; 561a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 562a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 563a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood} 564a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 56599e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 56698693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 56798693f674125484de8873d969c209276a6dd604bMike Lockwood 56898693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 56998693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, code); 57099e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood mRequest.setParameter(2, format); 57198693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 57298693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 57398693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 57498693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 57598693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 57698693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 57798693f674125484de8873d969c209276a6dd604bMike Lockwood MtpProperty* property = new MtpProperty; 57898693f674125484de8873d969c209276a6dd604bMike Lockwood property->read(mData); 57998693f674125484de8873d969c209276a6dd604bMike Lockwood return property; 58098693f674125484de8873d969c209276a6dd604bMike Lockwood } 58198693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 58298693f674125484de8873d969c209276a6dd604bMike Lockwood} 58398693f674125484de8873d969c209276a6dd604bMike Lockwood 58423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, 58523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool (* callback)(void* data, int offset, int length, void* clientData), 58623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int objectSize, void* clientData) { 58723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood Mutex::Autolock autoLock(mMutex); 58823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool result = false; 58923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 59023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.reset(); 59123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.setParameter(1, handle); 59223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 59323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood && mData.readDataHeader(mRequestIn1)) { 59423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t length = mData.getContainerLength(); 59523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) { 59629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readObject error objectSize: %d, length: %d", 59723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood objectSize, length); 59823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 59923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 60023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 60123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t remaining = length; 60223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int offset = 0; 60323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 60423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int initialDataLength = 0; 60523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* initialData = mData.getData(initialDataLength); 60623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialData) { 60723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialDataLength > 0) { 60823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(initialData, 0, initialDataLength, clientData)) 60923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 61023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= initialDataLength; 61123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += initialDataLength; 61223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 61323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood free(initialData); 61423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 61523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 61623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // USB reads greater than 16K don't work 61723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char buffer1[16384], buffer2[16384]; 61823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn1->buffer = buffer1; 61923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn2->buffer = buffer2; 62023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_request* req = mRequestIn1; 62123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* writeBuffer = NULL; 62223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int writeLength = 0; 62323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 62423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood while (remaining > 0 || writeBuffer) { 62523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (remaining > 0) { 62623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // queue up a read request 62723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 62823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (mData.readDataAsync(req)) { 62929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 63023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 63123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 63223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 63323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = NULL; 63423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 63523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 63623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (writeBuffer) { 63723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // write previous buffer 63823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(writeBuffer, offset, writeLength, clientData)) { 63929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 64023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for pending read before failing 64123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) 64223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mData.readDataWait(mDevice); 64323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 64423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 64523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += writeLength; 64623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 64723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 64823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 64923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for read to complete 65023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) { 65123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int read = mData.readDataWait(mDevice); 65223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read < 0) 65323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 65423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 65523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 65623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 65723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 65823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 65923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 66023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 66123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 66223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 66323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 66423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 66523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 66623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpResponseCode response = readResponse(); 66723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (response == MTP_RESPONSE_OK) 66823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood result = true; 66923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 67023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 67123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodfail: 67223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return result; 67323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 67423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 67523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 676b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path 67727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { 678b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readObject: %s", destPath); 679af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 680b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (fd < 0) { 68129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s", destPath); 682b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return false; 6830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 6840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 68527afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchown(fd, getuid(), group); 68627afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood // set permissions 68727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood int mask = umask(0); 68827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchmod(fd, perm); 68927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood umask(mask); 69027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood 691b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood Mutex::Autolock autoLock(mMutex); 692b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood bool result = false; 6930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 694b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.reset(); 695b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.setParameter(1, handle); 696b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 69742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood && mData.readDataHeader(mRequestIn1)) { 698b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t length = mData.getContainerLength(); 699b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (length < MTP_CONTAINER_HEADER_SIZE) 700b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 701b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 702b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t remaining = length; 703b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 704b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int initialDataLength = 0; 705b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood void* initialData = mData.getData(initialDataLength); 706b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialData) { 707b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialDataLength > 0) { 70831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (write(fd, initialData, initialDataLength) != initialDataLength) { 70931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(initialData); 710b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 71131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 712b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood remaining -= initialDataLength; 7130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 714b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood free(initialData); 7150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 717b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // USB reads greater than 16K don't work 718b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood char buffer1[16384], buffer2[16384]; 71942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1->buffer = buffer1; 72042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2->buffer = buffer2; 72142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood struct usb_request* req = mRequestIn1; 72242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood void* writeBuffer = NULL; 723b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int writeLength = 0; 724b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 725b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood while (remaining > 0 || writeBuffer) { 726b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (remaining > 0) { 727b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // queue up a read request 72842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 72942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (mData.readDataAsync(req)) { 73029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 731b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 732b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 73442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req = NULL; 7350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 737b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (writeBuffer) { 738b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // write previous buffer 739b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (write(fd, writeBuffer, writeLength) != writeLength) { 74029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 741b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for pending read before failing 74242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) 74342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mData.readDataWait(mDevice); 744b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 745b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 746b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood writeBuffer = NULL; 747b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 749b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for read to complete 75042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) { 75142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int read = mData.readDataWait(mDevice); 752b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (read < 0) 753b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 7540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 75523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 75623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 75723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 75823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 75923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 76023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 76123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 76223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 763b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 764b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 765b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 766b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood MtpResponseCode response = readResponse(); 767b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (response == MTP_RESPONSE_OK) 768b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood result = true; 7690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 770b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 771b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwoodfail: 772b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood ::close(fd); 773b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return result; 7740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 775a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 7765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) { 7773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation)); 778f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 7795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setOperationCode(operation); 7805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mTransactionID > 0) 7815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setTransactionID(mTransactionID++); 78242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mRequest.write(mRequestOut); 7835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.dump(); 7845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 7855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 7865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 7870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() { 7883856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendData\n"); 7895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 7905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 79142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.write(mRequestOut); 7925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 7935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 7945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 7955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 7965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() { 7975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.reset(); 79842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.read(mRequestIn1); 7993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readData returned %d\n", ret); 8005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 801f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 802b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("got response packet instead of data packet"); 803f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // we got a response packet rather than data 804f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // copy it to mResponse 805f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mResponse.copyFrom(mData); 806f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = true; 807f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return false; 808f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 8095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 8105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 8115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else { 8133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse failed\n"); 8145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 8155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) { 8190cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setOperationCode(operation); 8200cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 82142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood return (!mData.writeDataHeader(mRequestOut, dataLength)); 8220cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 8230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 8245ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() { 8253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse\n"); 826f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mReceivedResponse) { 827f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 828f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return mResponse.getResponseCode(); 829f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 83042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mResponse.read(mRequestIn1); 8313d74457b66533b170606347e60628e55a2af255eMike Lockwood // handle zero length packets, which might occur if the data transfer 8323d74457b66533b170606347e60628e55a2af255eMike Lockwood // ends on a packet boundary 8333d74457b66533b170606347e60628e55a2af255eMike Lockwood if (ret == 0) 8343d74457b66533b170606347e60628e55a2af255eMike Lockwood ret = mResponse.read(mRequestIn1); 8355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 8365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mResponse.dump(); 8375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mResponse.getResponseCode(); 838f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } else { 839b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readResponse failed\n"); 8405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return -1; 8415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} // namespace android 845