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; 325ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 326ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 327ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 328ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3335ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() { 3340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS)) 3385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3485ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) { 3490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO)) 3545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpStorageInfo* info = new MtpStorageInfo(storageID); 360ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 361ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 362ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 363ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 3645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3685ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID, 3695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectFormat format, MtpObjectHandle parent) { 3700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(2, format); 3755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(3, parent); 3765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES)) 3775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3875ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) { 3880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3906afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood // FIXME - we might want to add some caching here 3916afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 3925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, handle); 3945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO)) 3955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectInfo* info = new MtpObjectInfo(handle); 401ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 402ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 403ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 404ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 4055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 4065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 4085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 4093e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) { 4100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4123e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.reset(); 4133e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.setParameter(1, handle); 4143e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) { 4153e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood MtpResponseCode ret = readResponse(); 4163e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4173e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return mData.getData(outLength); 4183e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4193e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4203e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood outLength = 0; 4213e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return NULL; 4226afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 4236afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) { 4250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpObjectHandle parent = info->mParent; 4290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (parent == 0) 4300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood parent = MTP_PARENT_ROOT; 4310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mStorageID); 4330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(2, info->mParent); 4340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mStorageID); 4360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mFormat); 4370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mProtectionStatus); 4380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mCompressedSize); 4390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mThumbFormat); 4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbCompressedSize); 4410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixWidth); 4420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixHeight); 4430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixWidth); 4440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixHeight); 4450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixDepth); 4460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mParent); 4470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mAssociationType); 4480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mAssociationDesc); 4490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mSequenceNumber); 4500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mName); 4510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char created[100], modified[100]; 4530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateCreated, created, sizeof(created)); 4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateModified, modified, sizeof(modified)); 4550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(created); 4570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(modified); 4580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (info->mKeywords) 4590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mKeywords); 4600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood else 4610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putEmptyString(); 4620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 4640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mStorageID = mResponse.getParameter(1); 4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mParent = mResponse.getParameter(2); 4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mHandle = mResponse.getParameter(3); 4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return info->mHandle; 4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (MtpObjectHandle)-1; 4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 4740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) { 4760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int remaining = info->mCompressedSize; 4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mHandle); 4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // send data header 4830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining); 4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char buffer[65536]; 4860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood while (remaining > 0) { 4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood int count = read(srcFD, buffer, sizeof(buffer)); 4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (count > 0) { 48942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int written = mData.write(mRequestOut, buffer, count); 4900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood // FIXME check error 4910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood remaining -= count; 4920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 4930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood break; 4940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 4970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (remaining == 0 && ret == MTP_RESPONSE_OK); 4990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 5000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 5016afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) { 5020cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 5046afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.reset(); 5056afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.setParameter(1, handle); 5066afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 5076afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpResponseCode ret = readResponse(); 5086afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (ret == MTP_RESPONSE_OK) 5096afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return true; 5106afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood } 5116afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return false; 5126afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5136afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 5146afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 5156afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 51631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 51731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle parent = info->mParent; 51831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 51931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return parent; 52031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5216afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 52231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5236afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5243e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 5256afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 5266afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 52731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 52831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle storageId = info->mStorageID; 52931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 53031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return storageId; 53131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5326afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 53331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5343e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood} 5353e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 53698693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 53798693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 53898693f674125484de8873d969c209276a6dd604bMike Lockwood 53998693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 54098693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, format); 54198693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 54298693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 54398693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 54498693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 54598693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 54698693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 54798693f674125484de8873d969c209276a6dd604bMike Lockwood return mData.getAUInt16(); 54898693f674125484de8873d969c209276a6dd604bMike Lockwood } 54998693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 55098693f674125484de8873d969c209276a6dd604bMike Lockwood 55198693f674125484de8873d969c209276a6dd604bMike Lockwood} 55298693f674125484de8873d969c209276a6dd604bMike Lockwood 553a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 5540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 556a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.reset(); 557a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.setParameter(1, code); 558a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 559a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 560a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!readData()) 561a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 562a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpResponseCode ret = readResponse(); 563a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (ret == MTP_RESPONSE_OK) { 564a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = new MtpProperty; 565ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (property->read(mData)) 566ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return property; 567ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 568ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete property; 569a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 570a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 571a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood} 572a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 57399e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 57498693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 57598693f674125484de8873d969c209276a6dd604bMike Lockwood 57698693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 57798693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, code); 57899e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood mRequest.setParameter(2, format); 57998693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 58098693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 58198693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 58298693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 58398693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 58498693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 58598693f674125484de8873d969c209276a6dd604bMike Lockwood MtpProperty* property = new MtpProperty; 586ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (property->read(mData)) 587ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return property; 588ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 589ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete property; 59098693f674125484de8873d969c209276a6dd604bMike Lockwood } 59198693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 59298693f674125484de8873d969c209276a6dd604bMike Lockwood} 59398693f674125484de8873d969c209276a6dd604bMike Lockwood 59423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, 59523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool (* callback)(void* data, int offset, int length, void* clientData), 596ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood size_t objectSize, void* clientData) { 59723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood Mutex::Autolock autoLock(mMutex); 59823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood bool result = false; 59923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 60023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.reset(); 60123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequest.setParameter(1, handle); 60223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 60323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood && mData.readDataHeader(mRequestIn1)) { 60423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t length = mData.getContainerLength(); 60523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) { 60629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readObject error objectSize: %d, length: %d", 60723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood objectSize, length); 60823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 60923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 61023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 61123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint32_t remaining = length; 61223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int offset = 0; 61323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 61423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int initialDataLength = 0; 61523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* initialData = mData.getData(initialDataLength); 61623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialData) { 61723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (initialDataLength > 0) { 61823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(initialData, 0, initialDataLength, clientData)) 61923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 62023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= initialDataLength; 62123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += initialDataLength; 62223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 62323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood free(initialData); 62423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 62523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 62623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // USB reads greater than 16K don't work 62723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char buffer1[16384], buffer2[16384]; 62823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn1->buffer = buffer1; 62923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mRequestIn2->buffer = buffer2; 63023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_request* req = mRequestIn1; 63123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood void* writeBuffer = NULL; 63223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int writeLength = 0; 63323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 63423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood while (remaining > 0 || writeBuffer) { 63523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (remaining > 0) { 63623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // queue up a read request 63723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 63823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (mData.readDataAsync(req)) { 63929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 64023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 64123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 64223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 64323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = NULL; 64423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 64523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 64623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (writeBuffer) { 64723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // write previous buffer 64823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!callback(writeBuffer, offset, writeLength, clientData)) { 64929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 65023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for pending read before failing 65123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) 65223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mData.readDataWait(mDevice); 65323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 65423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 65523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood offset += writeLength; 65623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 65723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 65823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 65923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // wait for read to complete 66023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (req) { 66123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood int read = mData.readDataWait(mDevice); 66223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read < 0) 66323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood goto fail; 66423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 66523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 66623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 66723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 66823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 66923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 67023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 67123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 67223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 67323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 67423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 67523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 67623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpResponseCode response = readResponse(); 67723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (response == MTP_RESPONSE_OK) 67823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood result = true; 67923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 68023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 68123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodfail: 68223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return result; 68323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 68423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 68523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 686b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path 68727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { 688b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readObject: %s", destPath); 689af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 690b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (fd < 0) { 69129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s", destPath); 692b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return false; 6930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 6940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 69527afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchown(fd, getuid(), group); 69627afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood // set permissions 69727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood int mask = umask(0); 69827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchmod(fd, perm); 69927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood umask(mask); 70027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood 701b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood Mutex::Autolock autoLock(mMutex); 702b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood bool result = false; 7030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 704b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.reset(); 705b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.setParameter(1, handle); 706b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (sendRequest(MTP_OPERATION_GET_OBJECT) 70742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood && mData.readDataHeader(mRequestIn1)) { 708b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t length = mData.getContainerLength(); 709b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (length < MTP_CONTAINER_HEADER_SIZE) 710b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 711b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood length -= MTP_CONTAINER_HEADER_SIZE; 712b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood uint32_t remaining = length; 713b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 714b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int initialDataLength = 0; 715b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood void* initialData = mData.getData(initialDataLength); 716b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialData) { 717b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialDataLength > 0) { 71831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (write(fd, initialData, initialDataLength) != initialDataLength) { 71931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(initialData); 720b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 72131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 722b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood remaining -= initialDataLength; 7230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 724b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood free(initialData); 7250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 727b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // USB reads greater than 16K don't work 728b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood char buffer1[16384], buffer2[16384]; 72942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1->buffer = buffer1; 73042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2->buffer = buffer2; 73142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood struct usb_request* req = mRequestIn1; 73242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood void* writeBuffer = NULL; 733b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int writeLength = 0; 734b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 735b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood while (remaining > 0 || writeBuffer) { 736b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (remaining > 0) { 737b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // queue up a read request 73842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining); 73942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (mData.readDataAsync(req)) { 74029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("readDataAsync failed"); 741b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 742b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } else { 74442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood req = NULL; 7450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 747b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (writeBuffer) { 748b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // write previous buffer 749b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (write(fd, writeBuffer, writeLength) != writeLength) { 75029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("write failed"); 751b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for pending read before failing 75242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) 75342d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mData.readDataWait(mDevice); 754b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 755b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 756b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood writeBuffer = NULL; 757b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 759b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood // wait for read to complete 76042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood if (req) { 76142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int read = mData.readDataWait(mDevice); 762b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (read < 0) 763b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood goto fail; 7640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 76523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (read > 0) { 76623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = req->buffer; 76723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeLength = read; 76823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood remaining -= read; 76923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 77023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 77123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood writeBuffer = NULL; 77223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 773b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 774b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 775b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 776b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood MtpResponseCode response = readResponse(); 777b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (response == MTP_RESPONSE_OK) 778b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood result = true; 7790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 780b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 781b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwoodfail: 782b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood ::close(fd); 783b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return result; 7840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 785a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 7865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) { 7873856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation)); 788f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 7895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setOperationCode(operation); 7905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mTransactionID > 0) 7915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setTransactionID(mTransactionID++); 79242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mRequest.write(mRequestOut); 7935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.dump(); 7945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 7955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 7965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 7970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() { 7983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendData\n"); 7995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 8005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 80142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.write(mRequestOut); 8025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 8035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 8045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() { 8075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.reset(); 80842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.read(mRequestIn1); 8093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readData returned %d\n", ret); 8105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 811f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 812b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("got response packet instead of data packet"); 813f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // we got a response packet rather than data 814f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // copy it to mResponse 815f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mResponse.copyFrom(mData); 816f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = true; 817f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return false; 818f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 8195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 8205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 8215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else { 8233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse failed\n"); 8245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 8255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) { 8290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setOperationCode(operation); 8300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 83142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood return (!mData.writeDataHeader(mRequestOut, dataLength)); 8320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 8330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 8345ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() { 8353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse\n"); 836f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mReceivedResponse) { 837f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 838f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return mResponse.getResponseCode(); 839f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 84042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mResponse.read(mRequestIn1); 8413d74457b66533b170606347e60628e55a2af255eMike Lockwood // handle zero length packets, which might occur if the data transfer 8423d74457b66533b170606347e60628e55a2af255eMike Lockwood // ends on a packet boundary 8433d74457b66533b170606347e60628e55a2af255eMike Lockwood if (ret == 0) 8443d74457b66533b170606347e60628e55a2af255eMike Lockwood ret = mResponse.read(mRequestIn1); 8455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 8465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mResponse.dump(); 8475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mResponse.getResponseCode(); 848f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } else { 849b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readResponse failed\n"); 8505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return -1; 8515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} // namespace android 855