MtpDevice.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
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; 13423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood for (int i = 0; i < 3; i++) { 13523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter); 13623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) { 13729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 13831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 13923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 14023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 14123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { 14223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 14323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc = ep; 14423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood else 14523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_out_desc = ep; 14623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT && 14723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 14823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_intr_desc = ep; 14923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 15023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 15123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) { 15229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 15331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 15423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 15523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 15623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 15723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (usb_device_claim_interface(device, interface->bInterfaceNumber)) { 15829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("usb_device_claim_interface failed errno: %d\n", errno); 15931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 16023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 16123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 16223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 16323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber, 16423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc, ep_out_desc, ep_intr_desc); 16523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mtpDevice->initialize(); 16623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return mtpDevice; 16723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 16823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 16923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 17023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood usb_device_close(device); 17129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("device not found"); 17223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 17323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 17423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 1755ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface, 17642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_in, 17742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_out, 17842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_intr) 1795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood : mDevice(device), 1805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mInterface(interface), 18142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1(NULL), 18242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2(NULL), 18342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut(NULL), 18442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr(NULL), 1855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo(NULL), 1865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID(0), 187f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mTransactionID(0), 188f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse(false) 1895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{ 19042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1 = usb_request_new(device, ep_in); 19142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2 = usb_request_new(device, ep_in); 19242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut = usb_request_new(device, ep_out); 19342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr = usb_request_new(device, ep_intr); 1945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 1955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 1965ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() { 1975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood close(); 198a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood for (int i = 0; i < mDeviceProperties.size(); i++) 199a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood delete mDeviceProperties[i]; 20042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn1); 20142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn2); 20242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestOut); 20342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIntr); 2045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() { 2075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood openSession(); 2085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo = getDeviceInfo(); 2095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDeviceInfo) { 210a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (mDeviceInfo->mDeviceProperties) { 211a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 212a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood for (int i = 0; i < count; i++) { 213a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 214a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2150c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) 216a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mDeviceProperties.push(property); 217a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 218a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 2195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() { 2235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) { 2245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_release_interface(mDevice, mInterface); 2255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_close(mDevice); 2265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDevice = NULL; 2275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2300c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwoodvoid MtpDevice::print() { 2310c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo) { 2320c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood mDeviceInfo->print(); 2330c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2340c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mDeviceProperties) { 235df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** DEVICE PROPERTIES *****\n"); 2360c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 2370c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2380c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 2390c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2400c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) { 2410c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 24231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 2430c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2440c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2450c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2460c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2470c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2480c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mPlaybackFormats) { 249df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** OBJECT PROPERTIES *****\n"); 2500c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mPlaybackFormats->size(); 2510c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2520c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i]; 253df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format)); 2540c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectPropertyList* props = getObjectPropsSupported(format); 2550c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (props) { 2560c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int j = 0; j < props->size(); j++) { 2570c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectProperty prop = (*props)[j]; 25899e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood MtpProperty* property = getObjectPropDesc(prop, format); 25931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (property) { 2600c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 26131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 26231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 26329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("could not fetch property: %s", 2640c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDebug::getObjectPropCodeName(prop)); 26531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 2660c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2670c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2680c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2690c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2700c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood} 2710c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() { 2735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) 2745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return usb_device_get_name(mDevice); 2755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else 2765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return "???"; 2775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() { 2800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 2810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 2825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = 0; 2835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 0; 2845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpSessionID newSession = 1; 2855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 2865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, newSession); 2875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_OPEN_SESSION)) 2885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 2895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 2905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN) 2915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood newSession = mResponse.getParameter(1); 2925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else if (ret != MTP_RESPONSE_OK) 2935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 2945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = newSession; 2965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 1; 2975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 2985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() { 3015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood // FIXME 3025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 3035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3055ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() { 3060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3070cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO)) 3105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpDeviceInfo* info = new MtpDeviceInfo; 3165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3225ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() { 3230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS)) 3275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) { 3380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO)) 3435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpStorageInfo* info = new MtpStorageInfo(storageID); 3495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3555ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID, 3565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectFormat format, MtpObjectHandle parent) { 3570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(2, format); 3625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(3, parent); 3635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES)) 3645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) { 3750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3776afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood // FIXME - we might want to add some caching here 3786afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 3795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, handle); 3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO)) 3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectInfo* info = new MtpObjectInfo(handle); 3885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood info->read(mData); 3895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return info; 3905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3943e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) { 3950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3973e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.reset(); 3983e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.setParameter(1, handle); 3993e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) { 4003e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood MtpResponseCode ret = readResponse(); 4013e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4023e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return mData.getData(outLength); 4033e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4043e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4053e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood outLength = 0; 4063e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return NULL; 4076afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 4086afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4090cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) { 4100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4120cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpObjectHandle parent = info->mParent; 4140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (parent == 0) 4150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood parent = MTP_PARENT_ROOT; 4160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mStorageID); 4180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(2, info->mParent); 4190cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4200cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mStorageID); 4210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mFormat); 4220cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mProtectionStatus); 4230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mCompressedSize); 4240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mThumbFormat); 4250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbCompressedSize); 4260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixWidth); 4270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixHeight); 4280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixWidth); 4290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixHeight); 4300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixDepth); 4310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mParent); 4320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mAssociationType); 4330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mAssociationDesc); 4340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mSequenceNumber); 4350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mName); 4360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char created[100], modified[100]; 4380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateCreated, created, sizeof(created)); 4390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateModified, modified, sizeof(modified)); 4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(created); 4420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(modified); 4430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (info->mKeywords) 4440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mKeywords); 4450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood else 4460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putEmptyString(); 4470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 4490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mStorageID = mResponse.getParameter(1); 4520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mParent = mResponse.getParameter(2); 4530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mHandle = mResponse.getParameter(3); 4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return info->mHandle; 4550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (MtpObjectHandle)-1; 4580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 4590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) { 4610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int remaining = info->mCompressedSize; 4640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mHandle); 4660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // send data header 4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining); 4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char buffer[65536]; 4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood while (remaining > 0) { 4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int count = read(srcFD, buffer, sizeof(buffer)); 4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (count > 0) { 47442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int written = mData.write(mRequestOut, buffer, count); 4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // FIXME check error 4760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood remaining -= count; 4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood break; 4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (remaining == 0 && ret == MTP_RESPONSE_OK); 4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4866afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) { 4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4896afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.reset(); 4906afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.setParameter(1, handle); 4916afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 4926afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpResponseCode ret = readResponse(); 4936afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (ret == MTP_RESPONSE_OK) 4946afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return true; 4956afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood } 4966afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return false; 4976afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 4986afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4996afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 5006afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 50131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 50231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle parent = info->mParent; 50331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 50431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return parent; 50531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5066afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 50731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5086afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5093e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 5106afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 5116afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 51231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 51331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle storageId = info->mStorageID; 51431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 51531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return storageId; 51631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5176afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 51831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5193e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood} 5203e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 52198693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 52298693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 52398693f674125484de8873d969c209276a6dd604bMike Lockwood 52498693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 52598693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, format); 52698693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 52798693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 52898693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 52998693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 53098693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 53198693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 53298693f674125484de8873d969c209276a6dd604bMike Lockwood return mData.getAUInt16(); 53398693f674125484de8873d969c209276a6dd604bMike Lockwood } 53498693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 53598693f674125484de8873d969c209276a6dd604bMike Lockwood 53698693f674125484de8873d969c209276a6dd604bMike Lockwood} 53798693f674125484de8873d969c209276a6dd604bMike Lockwood 538a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 5390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 541a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.reset(); 542a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.setParameter(1, code); 543a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 544a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 545a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!readData()) 546a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 547a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpResponseCode ret = readResponse(); 548a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (ret == MTP_RESPONSE_OK) { 549a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = new MtpProperty; 550e3e76c456baee122de6715ae280130abaddc906cMike Lockwood property->read(mData); 551a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return property; 552a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 553a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 554a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood} 555a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 55699e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 55798693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 55898693f674125484de8873d969c209276a6dd604bMike Lockwood 55998693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 56098693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, code); 56199e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood mRequest.setParameter(2, format); 56298693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 56398693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 56498693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 56598693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 56698693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 56798693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 56898693f674125484de8873d969c209276a6dd604bMike Lockwood MtpProperty* property = new MtpProperty; 56998693f674125484de8873d969c209276a6dd604bMike Lockwood property->read(mData); 57098693f674125484de8873d969c209276a6dd604bMike Lockwood return property; 57198693f674125484de8873d969c209276a6dd604bMike Lockwood } 57298693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 57398693f674125484de8873d969c209276a6dd604bMike Lockwood} 57498693f674125484de8873d969c209276a6dd604bMike Lockwood 57523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, 57623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool (* callback)(void* data, int offset, int length, void* clientData), 57723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int objectSize, void* clientData) { 57823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood Mutex::Autolock autoLock(mMutex); 57923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool result = false; 58023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 58123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.reset(); 58223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.setParameter(1, handle); 58323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 58423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood && mData.readDataHeader(mRequestIn1)) { 58523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t length = mData.getContainerLength(); 58623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) { 58729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readObject error objectSize: %d, length: %d", 58823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood objectSize, length); 58923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 59023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 59123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 59223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t remaining = length; 59323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int offset = 0; 59423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 59523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int initialDataLength = 0; 59623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* initialData = mData.getData(initialDataLength); 59723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialData) { 59823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialDataLength > 0) { 59923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(initialData, 0, initialDataLength, clientData)) 60023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 60123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= initialDataLength; 60223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += initialDataLength; 60323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 60423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood free(initialData); 60523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 60623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 60723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // USB reads greater than 16K don't work 60823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char buffer1[16384], buffer2[16384]; 60923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn1->buffer = buffer1; 61023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn2->buffer = buffer2; 61123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_request* req = mRequestIn1; 61223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* writeBuffer = NULL; 61323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int writeLength = 0; 61423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 61523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood while (remaining > 0 || writeBuffer) { 61623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (remaining > 0) { 61723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // queue up a read request 61823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 61923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (mData.readDataAsync(req)) { 62029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 62123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 62223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 62323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 62423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = NULL; 62523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 62623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 62723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (writeBuffer) { 62823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // write previous buffer 62923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(writeBuffer, offset, writeLength, clientData)) { 63029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 63123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for pending read before failing 63223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) 63323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mData.readDataWait(mDevice); 63423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 63523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 63623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += writeLength; 63723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 63823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 63923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 64023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for read to complete 64123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) { 64223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int read = mData.readDataWait(mDevice); 64323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read < 0) 64423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 64523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 64623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 64723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 64823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 64923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 65023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 65123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 65223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 65323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 65423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 65523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 65623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 65723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpResponseCode response = readResponse(); 65823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (response == MTP_RESPONSE_OK) 65923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood result = true; 66023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 66123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 66223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodfail: 66323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return result; 66423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 66523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 66623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 667b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path 66827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { 669b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readObject: %s", destPath); 670b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC); 671b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (fd < 0) { 67229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s", destPath); 673b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return false; 6740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 6750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 67627afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchown(fd, getuid(), group); 67727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood // set permissions 67827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood int mask = umask(0); 67927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchmod(fd, perm); 68027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood umask(mask); 68127afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood 682b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood Mutex::Autolock autoLock(mMutex); 683b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood bool result = false; 6840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 685b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.reset(); 686b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.setParameter(1, handle); 687b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 68842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood && mData.readDataHeader(mRequestIn1)) { 689b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t length = mData.getContainerLength(); 690b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (length < MTP_CONTAINER_HEADER_SIZE) 691b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 692b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 693b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t remaining = length; 694b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 695b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int initialDataLength = 0; 696b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood void* initialData = mData.getData(initialDataLength); 697b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialData) { 698b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialDataLength > 0) { 69931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (write(fd, initialData, initialDataLength) != initialDataLength) { 70031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(initialData); 701b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 70231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 703b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood remaining -= initialDataLength; 7040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 705b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood free(initialData); 7060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7070cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 708b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // USB reads greater than 16K don't work 709b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood char buffer1[16384], buffer2[16384]; 71042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1->buffer = buffer1; 71142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2->buffer = buffer2; 71242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood struct usb_request* req = mRequestIn1; 71342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood void* writeBuffer = NULL; 714b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int writeLength = 0; 715b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 716b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood while (remaining > 0 || writeBuffer) { 717b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (remaining > 0) { 718b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // queue up a read request 71942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 72042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (mData.readDataAsync(req)) { 72129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 722b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 723b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 72542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req = NULL; 7260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 728b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (writeBuffer) { 729b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // write previous buffer 730b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (write(fd, writeBuffer, writeLength) != writeLength) { 73129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 732b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for pending read before failing 73342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) 73442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mData.readDataWait(mDevice); 735b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 736b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 737b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood writeBuffer = NULL; 738b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 740b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for read to complete 74142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) { 74242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int read = mData.readDataWait(mDevice); 743b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (read < 0) 744b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 7450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 74623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 74723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 74823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 74923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 75023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 75123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 75223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 75323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 754b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 755b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 756b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 757b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood MtpResponseCode response = readResponse(); 758b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (response == MTP_RESPONSE_OK) 759b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood result = true; 7600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 761b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 762b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwoodfail: 763b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood ::close(fd); 764b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return result; 7650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 766a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 7675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) { 7683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation)); 769f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 7705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setOperationCode(operation); 7715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mTransactionID > 0) 7725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setTransactionID(mTransactionID++); 77342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mRequest.write(mRequestOut); 7745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.dump(); 7755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 7765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 7775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 7780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() { 7793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendData\n"); 7805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 7815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 78242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.write(mRequestOut); 7835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 7845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 7855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 7865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 7875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() { 7885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.reset(); 78942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.read(mRequestIn1); 7903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readData returned %d\n", ret); 7915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 792f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 793b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("got response packet instead of data packet"); 794f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // we got a response packet rather than data 795f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // copy it to mResponse 796f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mResponse.copyFrom(mData); 797f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = true; 798f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return false; 799f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 8005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 8015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 8025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else { 8043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse failed\n"); 8055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 8065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8090cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) { 8100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setOperationCode(operation); 8110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 81242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood return (!mData.writeDataHeader(mRequestOut, dataLength)); 8130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 8140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 8155ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() { 8163856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse\n"); 817f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mReceivedResponse) { 818f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 819f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return mResponse.getResponseCode(); 820f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 82142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mResponse.read(mRequestIn1); 8223d74457b66533b170606347e60628e55a2af255eMike Lockwood // handle zero length packets, which might occur if the data transfer 8233d74457b66533b170606347e60628e55a2af255eMike Lockwood // ends on a packet boundary 8243d74457b66533b170606347e60628e55a2af255eMike Lockwood if (ret == 0) 8253d74457b66533b170606347e60628e55a2af255eMike Lockwood ret = mResponse.read(mRequestIn1); 8265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 8275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mResponse.dump(); 8285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mResponse.getResponseCode(); 829f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } else { 830b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readResponse failed\n"); 8315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return -1; 8325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} // namespace android 836