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" 224fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono#include "MtpEventPacket.h" 23b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpObjectInfo.h" 24b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpProperty.h" 25b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStorageInfo.h" 26b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpStringBuffer.h" 270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include "MtpUtils.h" 28a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdio.h> 305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <stdlib.h> 315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/types.h> 325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/ioctl.h> 335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <sys/stat.h> 345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <fcntl.h> 355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <errno.h> 360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood#include <endian.h> 375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood#include <usbhost/usbhost.h> 395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodnamespace android { 415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 42d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0 4323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodstatic bool isMtpDevice(uint16_t vendor, uint16_t product) { 4423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Sandisk Sansa Fuze 4523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (vendor == 0x0781 && product == 0x74c2) 4623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return true; 4723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Samsung YP-Z5 4823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (vendor == 0x04e8 && product == 0x503c) 4923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return true; 5023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return false; 5123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 52d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif 5323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirononamespace { 554fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 564a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool writeToFd(void* data, uint32_t /* unused_offset */, uint32_t length, void* clientData) { 574fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono const int fd = *static_cast<int*>(clientData); 584a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono const ssize_t result = write(fd, data, length); 594a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono if (result < 0) { 604a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return false; 614a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono } 624a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return static_cast<uint32_t>(result) == length; 634fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono} 644fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 654a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono} // namespace 664fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 6723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike LockwoodMtpDevice* MtpDevice::open(const char* deviceName, int fd) { 6823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_device *device = usb_device_new(deviceName, fd); 6923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!device) { 7029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("usb_device_new failed for %s", deviceName); 7123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 7223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 7323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 7423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_descriptor_header* desc; 7523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_descriptor_iter iter; 7623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 7723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood usb_descriptor_iter_init(device, &iter); 7823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 7923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood while ((desc = usb_descriptor_iter_next(&iter)) != NULL) { 8023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (desc->bDescriptorType == USB_DT_INTERFACE) { 8123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc; 8223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 8323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE && 8423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceSubClass == 1 && // Still Image Capture 8523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceProtocol == 1) // Picture Transfer Protocol (PIMA 15470) 8623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood { 8731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* manufacturerName = usb_device_get_manufacturer_name(device); 8831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* productName = usb_device_get_product_name(device); 89b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName); 9031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(manufacturerName); 9131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(productName); 9223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else if (interface->bInterfaceClass == 0xFF && 9323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceSubClass == 0xFF && 9423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood interface->bInterfaceProtocol == 0) { 9523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char* interfaceName = usb_device_get_string(device, interface->iInterface); 9631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (!interfaceName) { 9723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood continue; 9831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else if (strcmp(interfaceName, "MTP")) { 9931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(interfaceName); 10031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root continue; 10131c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 10231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(interfaceName); 10331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root 10423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // Looks like an android style MTP device 10531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* manufacturerName = usb_device_get_manufacturer_name(device); 10631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root char* productName = usb_device_get_product_name(device); 107b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName); 10831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(manufacturerName); 10931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root free(productName); 110d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood } 111d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#if 0 112d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood else { 11323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // look for special cased devices based on vendor/product ID 11423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // we are doing this mainly for testing purposes 11523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint16_t vendor = usb_device_get_vendor_id(device); 11623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood uint16_t product = usb_device_get_product_id(device); 11723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!isMtpDevice(vendor, product)) { 11823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // not an MTP or PTP device 11923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood continue; 12023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 12123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // request MTP OS string and descriptor 12223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // some music players need to see this before entering MTP mode. 12323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood char buffer[256]; 12423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood memset(buffer, 0, sizeof(buffer)); 125f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood int ret = usb_device_control_transfer(device, 12623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD, 12723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE, 128f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood 0, buffer, sizeof(buffer), 0); 129f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno); 13023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ret > 0) { 13123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("got MTP string %s\n", buffer); 132f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood ret = usb_device_control_transfer(device, 13323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1, 134f41ef0ee0da4c497352df42d09c3d89940c25e14Mike Lockwood 0, 4, buffer, sizeof(buffer), 0); 13523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("OS descriptor got %d\n", ret); 13623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else { 13723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood printf("no MTP string\n"); 13823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 13923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 140d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono#else 141d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono else { 142d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono continue; 143d6dabe95eb59c3d95f94825d08a6028bab06cbdcDaichi Hirono } 144d4fb52e3031578119ecd53087b1bcb4828c333c5Mike Lockwood#endif 14523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // if we got here, then we have a likely MTP or PTP device 14623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 14723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood // interface should be followed by three endpoints 14823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep; 14923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_in_desc = NULL; 15023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_out_desc = NULL; 15123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood struct usb_endpoint_descriptor *ep_intr_desc = NULL; 1528023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor; 1538023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL; 15423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood for (int i = 0; i < 3; i++) { 15523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter); 1568023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) { 1578023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ALOGD("Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n"); 1588023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep; 1598023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter); 1608023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang } 1618023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang 16223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) { 16329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 16431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 16523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 16623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 1678023f3af62795b7816f36a9423f8e0a39e616e49Bo Huang 16823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { 16923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) 17023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc = ep; 17123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood else 17223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_out_desc = ep; 17323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT && 17423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { 17523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_intr_desc = ep; 17623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 17723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 17823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) { 17929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("endpoints not found\n"); 18031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 18123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 18223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 18323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 18433d58162896868f387416289c8b33266be0a3360Jaesung Chung int ret = usb_device_claim_interface(device, interface->bInterfaceNumber); 18533d58162896868f387416289c8b33266be0a3360Jaesung Chung if (ret && errno == EBUSY) { 18633d58162896868f387416289c8b33266be0a3360Jaesung Chung // disconnect kernel driver and try again 18733d58162896868f387416289c8b33266be0a3360Jaesung Chung usb_device_connect_kernel_driver(device, interface->bInterfaceNumber, false); 18833d58162896868f387416289c8b33266be0a3360Jaesung Chung ret = usb_device_claim_interface(device, interface->bInterfaceNumber); 18933d58162896868f387416289c8b33266be0a3360Jaesung Chung } 19033d58162896868f387416289c8b33266be0a3360Jaesung Chung if (ret) { 19129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("usb_device_claim_interface failed errno: %d\n", errno); 19231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root usb_device_close(device); 19323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 19423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 19523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 19623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber, 19723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood ep_in_desc, ep_out_desc, ep_intr_desc); 19823f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood mtpDevice->initialize(); 19923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return mtpDevice; 20023f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 20123f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood } 20223f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 20323f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood usb_device_close(device); 20429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("device not found"); 20523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood return NULL; 20623f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 20723f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 2085ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface, 20942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_in, 21042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_out, 21142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood const struct usb_endpoint_descriptor *ep_intr) 2125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood : mDevice(device), 2135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mInterface(interface), 21442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1(NULL), 21542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2(NULL), 21642d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut(NULL), 21742d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr(NULL), 2185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo(NULL), 2195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID(0), 220f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mTransactionID(0), 2218a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mReceivedResponse(false), 2228a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mProcessingEvent(false), 2235c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono mCurrentEventHandle(0), 2245c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono mLastSendObjectInfoTransactionID(0), 225d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono mLastSendObjectInfoObjectHandle(0), 226d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD) 2275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{ 22842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn1 = usb_request_new(device, ep_in); 22942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIn2 = usb_request_new(device, ep_in); 23042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestOut = usb_request_new(device, ep_out); 23142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood mRequestIntr = usb_request_new(device, ep_intr); 2325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2345ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() { 2355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood close(); 2363ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mDeviceProperties.size(); i++) 237a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood delete mDeviceProperties[i]; 23842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn1); 23942d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIn2); 24042d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestOut); 24142d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood usb_request_free(mRequestIntr); 2425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() { 2455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood openSession(); 2465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDeviceInfo = getDeviceInfo(); 2475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDeviceInfo) { 248a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (mDeviceInfo->mDeviceProperties) { 249a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 250a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood for (int i = 0; i < count; i++) { 251a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 252a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2530c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) 254a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mDeviceProperties.push(property); 255a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 256a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 2575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() { 2615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) { 2625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_release_interface(mDevice, mInterface); 2635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood usb_device_close(mDevice); 2645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mDevice = NULL; 2655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 2665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 2675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 2680c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwoodvoid MtpDevice::print() { 2690c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo) { 2700c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood mDeviceInfo->print(); 2710c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2720c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mDeviceProperties) { 273df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** DEVICE PROPERTIES *****\n"); 2740c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mDeviceProperties->size(); 2750c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2760c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i]; 2770c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpProperty* property = getDevicePropDesc(propCode); 2780c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (property) { 2790c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 28031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 2810c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2820c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2830c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2840c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 2850c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 2860c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (mDeviceInfo->mPlaybackFormats) { 287df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("***** OBJECT PROPERTIES *****\n"); 2880c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood int count = mDeviceInfo->mPlaybackFormats->size(); 2890c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood for (int i = 0; i < count; i++) { 2900c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i]; 291df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format)); 2920c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectPropertyList* props = getObjectPropsSupported(format); 2930c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood if (props) { 2943ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t j = 0; j < props->size(); j++) { 2950c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpObjectProperty prop = (*props)[j]; 29699e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood MtpProperty* property = getObjectPropDesc(prop, format); 29731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (property) { 2980c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood property->print(); 29931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete property; 30031c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 30129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("could not fetch property: %s", 3020c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood MtpDebug::getObjectPropCodeName(prop)); 30331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 3040c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 3050c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 3060c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 3070c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood } 3080c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood} 3090c7c7c76a96a82ec728a2d5c091941c4057ffb25Mike Lockwood 3105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() { 3115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mDevice) 3125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return usb_device_get_name(mDevice); 3135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else 3145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return "???"; 3155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() { 3180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3190cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = 0; 3215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 0; 3225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpSessionID newSession = 1; 3235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, newSession); 3255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_OPEN_SESSION)) 3265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 3275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN) 3295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood newSession = mResponse.getParameter(1); 3305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else if (ret != MTP_RESPONSE_OK) 3315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 3325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mSessionID = newSession; 3345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mTransactionID = 1; 3355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 3365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() { 3395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood // FIXME 3405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 3415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3435ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() { 3440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO)) 3485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpDeviceInfo* info = new MtpDeviceInfo; 354ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 355ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 356ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 357ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 3585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3625ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() { 3630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS)) 3675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 3735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3775ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) { 3780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 3790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 3805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 3815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 3825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO)) 3835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 3855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 3875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 3885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpStorageInfo* info = new MtpStorageInfo(storageID); 389ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 390ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 391ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 392ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 3935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 3945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 3955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 3965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 3975ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID, 3985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectFormat format, MtpObjectHandle parent) { 3990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 4025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, storageID); 4035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(2, format); 4045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(3, parent); 4055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES)) 4065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 4085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 4105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mData.getAUInt32(); 4125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 4135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 4155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 4165ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) { 4170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4196afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood // FIXME - we might want to add some caching here 4206afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.reset(); 4225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setParameter(1, handle); 4235ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO)) 4245ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4255ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (!readData()) 4265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpResponseCode ret = readResponse(); 4285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood MtpObjectInfo* info = new MtpObjectInfo(handle); 430ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (info->read(mData)) 431ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return info; 432ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 433ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete info; 4345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 4355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return NULL; 4365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 4375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 4383e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) { 4390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4413e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.reset(); 4423e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood mRequest.setParameter(1, handle); 4433e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) { 4443e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood MtpResponseCode ret = readResponse(); 4453e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4464fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return mData.getData(&outLength); 4473e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4483e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood } 4493e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood outLength = 0; 4503e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood return NULL; 4516afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 4526afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 4530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) { 4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 4550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 4570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpObjectHandle parent = info->mParent; 4580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (parent == 0) 4590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood parent = MTP_PARENT_ROOT; 4600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.setParameter(1, info->mStorageID); 46264c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski mRequest.setParameter(2, parent); 4630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 46464c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski mData.reset(); 4650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mStorageID); 4660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mFormat); 4670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mProtectionStatus); 4680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mCompressedSize); 4690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mThumbFormat); 4700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbCompressedSize); 4710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixWidth); 4720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mThumbPixHeight); 4730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixWidth); 4740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixHeight); 4750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mImagePixDepth); 4760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mParent); 4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt16(info->mAssociationType); 4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mAssociationDesc); 4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putUInt32(info->mSequenceNumber); 4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mName); 4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood char created[100], modified[100]; 4830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateCreated, created, sizeof(created)); 4840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood formatDateTime(info->mDateModified, modified, sizeof(modified)); 4850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(created); 4870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(modified); 4880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (info->mKeywords) 4890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putString(info->mKeywords); 4900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood else 4910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mData.putEmptyString(); 4920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 4930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) { 4940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood MtpResponseCode ret = readResponse(); 4950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (ret == MTP_RESPONSE_OK) { 4965c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono mLastSendObjectInfoTransactionID = mRequest.getTransactionID(); 4975c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono mLastSendObjectInfoObjectHandle = mResponse.getParameter(3); 4980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mStorageID = mResponse.getParameter(1); 4990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mParent = mResponse.getParameter(2); 5000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood info->mHandle = mResponse.getParameter(3); 5010cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return info->mHandle; 5020cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 5030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 5040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood return (MtpObjectHandle)-1; 5050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 5060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 507532b4f23c7e08fdae9fff189c4b565f6216ffd2aTomasz Mikolajewskibool MtpDevice::sendObject(MtpObjectHandle handle, int size, int srcFD) { 5080cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5090cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 5105c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono if (mLastSendObjectInfoTransactionID + 1 != mTransactionID || 5115c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono mLastSendObjectInfoObjectHandle != handle) { 5125c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono ALOGE("A sendObject request must follow the sendObjectInfo request."); 5135c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono return false; 5145c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono } 5155c66471ad288640a89188f765fef5b41b4d3daf5Daichi Hirono 5160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood mRequest.reset(); 5170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood if (sendRequest(MTP_OPERATION_SEND_OBJECT)) { 518d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono mData.setOperationCode(mRequest.getOperationCode()); 519d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono mData.setTransactionID(mRequest.getTransactionID()); 520d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono const int writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size); 521d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono const MtpResponseCode ret = readResponse(); 522d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono return ret == MTP_RESPONSE_OK && writeResult > 0; 5230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 524d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono return false; 5250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 5260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 5276afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) { 5280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 5306afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.reset(); 5316afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood mRequest.setParameter(1, handle); 5326afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) { 5336afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpResponseCode ret = readResponse(); 5346afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood if (ret == MTP_RESPONSE_OK) 5356afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return true; 5366afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood } 5376afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return false; 5386afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5396afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood 5406afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) { 5416afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 54231c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 54331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle parent = info->mParent; 54431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 54531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return parent; 54631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5476afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 54831c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5496afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood} 5503e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 5516afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) { 5526afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood MtpObjectInfo* info = getObjectInfo(handle); 55331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root if (info) { 55431c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root MtpObjectHandle storageId = info->mStorageID; 55531c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root delete info; 55631c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root return storageId; 55731c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } else { 5586afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood return -1; 55931c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 5603e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood} 5613e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood 56298693f674125484de8873d969c209276a6dd604bMike LockwoodMtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) { 56398693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 56498693f674125484de8873d969c209276a6dd604bMike Lockwood 56598693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 56698693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, format); 56798693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED)) 56898693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 56998693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 57098693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 57198693f674125484de8873d969c209276a6dd604bMike Lockwood MtpResponseCode ret = readResponse(); 57298693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 57398693f674125484de8873d969c209276a6dd604bMike Lockwood return mData.getAUInt16(); 57498693f674125484de8873d969c209276a6dd604bMike Lockwood } 57598693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 57698693f674125484de8873d969c209276a6dd604bMike Lockwood 57798693f674125484de8873d969c209276a6dd604bMike Lockwood} 57898693f674125484de8873d969c209276a6dd604bMike Lockwood 579a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) { 5800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood Mutex::Autolock autoLock(mMutex); 5810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 582a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.reset(); 583a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood mRequest.setParameter(1, code); 584a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC)) 585a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 586a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (!readData()) 587a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 588a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpResponseCode ret = readResponse(); 589a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood if (ret == MTP_RESPONSE_OK) { 590a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood MtpProperty* property = new MtpProperty; 591ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (property->read(mData)) 592ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return property; 593ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 594ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete property; 595a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood } 596a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood return NULL; 597a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood} 598a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 59999e393a39a31bfbdeb435462939519e2d0279433Mike LockwoodMtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) { 60098693f674125484de8873d969c209276a6dd604bMike Lockwood Mutex::Autolock autoLock(mMutex); 60198693f674125484de8873d969c209276a6dd604bMike Lockwood 60298693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.reset(); 60398693f674125484de8873d969c209276a6dd604bMike Lockwood mRequest.setParameter(1, code); 60499e393a39a31bfbdeb435462939519e2d0279433Mike Lockwood mRequest.setParameter(2, format); 60598693f674125484de8873d969c209276a6dd604bMike Lockwood if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC)) 60698693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 60798693f674125484de8873d969c209276a6dd604bMike Lockwood if (!readData()) 60898693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 60966a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono const MtpResponseCode ret = readResponse(); 61098693f674125484de8873d969c209276a6dd604bMike Lockwood if (ret == MTP_RESPONSE_OK) { 61198693f674125484de8873d969c209276a6dd604bMike Lockwood MtpProperty* property = new MtpProperty; 612ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (property->read(mData)) 613ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return property; 614ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood else 615ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood delete property; 61698693f674125484de8873d969c209276a6dd604bMike Lockwood } 61798693f674125484de8873d969c209276a6dd604bMike Lockwood return NULL; 61898693f674125484de8873d969c209276a6dd604bMike Lockwood} 61998693f674125484de8873d969c209276a6dd604bMike Lockwood 62066a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hironobool MtpDevice::getObjectPropValue(MtpObjectHandle handle, MtpProperty* property) { 62166a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono if (property == nullptr) 62266a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono return false; 62366a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono 62466a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono Mutex::Autolock autoLock(mMutex); 62566a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono 62666a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono mRequest.reset(); 62766a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono mRequest.setParameter(1, handle); 62866a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono mRequest.setParameter(2, property->getPropertyCode()); 62966a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_VALUE)) 63066a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono return false; 63166a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono if (!readData()) 63266a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono return false; 63366a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono if (readResponse() != MTP_RESPONSE_OK) 63466a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono return false; 63566a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono property->setCurrentValue(mData); 63666a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono return true; 63766a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono} 63866a9abef47f7c8bd438bb1897617ebad3858c736Daichi Hirono 63923f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, 6404fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ReadObjectCallback callback, 6414a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono uint32_t expectedLength, 6424fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono void* clientData) { 6434fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return readObjectInternal(handle, callback, &expectedLength, clientData); 64423f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood} 64523f1b33c5f88f07510ca5dc01b3afd7af6843d6cMike Lockwood 646b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood// reads the object's data and writes it to the specified file path 64727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwoodbool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) { 648b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readObject: %s", destPath); 649af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 650b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (fd < 0) { 65129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s", destPath); 652b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood return false; 6530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 6540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 65527afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchown(fd, getuid(), group); 65627afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood // set permissions 65727afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood int mask = umask(0); 65827afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood fchmod(fd, perm); 65927afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood umask(mask); 66027afe3a1cc9c07ac4884a7720087a597aea3c76fMike Lockwood 661025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski bool result = readObject(handle, fd); 662025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski ::close(fd); 663025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski return result; 664025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski} 665025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski 666025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewskibool MtpDevice::readObject(MtpObjectHandle handle, int fd) { 667025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski ALOGD("readObject: %d", fd); 6684fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd); 6694fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono} 670025ffd9c17a7b30d862436954aa0db8d08bfaa9fTomasz Mikolajewski 6714fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hironobool MtpDevice::readObjectInternal(MtpObjectHandle handle, 6724fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ReadObjectCallback callback, 6734a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono const uint32_t* expectedLength, 6744fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono void* clientData) { 675b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood Mutex::Autolock autoLock(mMutex); 6760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 677b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.reset(); 678b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood mRequest.setParameter(1, handle); 6794fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (!sendRequest(MTP_OPERATION_GET_OBJECT)) { 6804fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("Failed to send a read request."); 6814fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return false; 6824fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 6834fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 6844a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return readData(callback, expectedLength, nullptr, clientData); 6854a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono} 6864a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono 6874a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool MtpDevice::readData(ReadObjectCallback callback, 6884a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono const uint32_t* expectedLength, 6894a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono uint32_t* writtenSize, 6904a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono void* clientData) { 6914fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (!mData.readDataHeader(mRequestIn1)) { 6924fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("Failed to read header."); 6934fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return false; 6944fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 6954fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 696d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // If object size 0 byte, the remote device may reply a response packet without sending any data 697d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // packets. 698a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 699a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono mResponse.copyFrom(mData); 700a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono return mResponse.getResponseCode() == MTP_RESPONSE_OK; 701a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono } 702a04e6fa61391f1ef64266579760f315c6b3e70b9Daichi Hirono 7034fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono const uint32_t fullLength = mData.getContainerLength(); 7044a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono if (fullLength < MTP_CONTAINER_HEADER_SIZE) { 7054a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono ALOGE("fullLength is too short: %d", fullLength); 7064a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return false; 7074a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono } 7084a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE; 7094a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono if (expectedLength && length != *expectedLength) { 7104fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("readObject error length: %d", fullLength); 7114fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return false; 7124fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 7134fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 7144fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono uint32_t offset = 0; 7154fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono bool writingError = false; 716b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 7174fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono { 718b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int initialDataLength = 0; 7194fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono void* const initialData = mData.getData(&initialDataLength); 720d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) { 721d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // According to the MTP spec, the responder (MTP device) can choose two ways of sending 722d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // data. a) The first packet contains the head and as much of the payload as possible 723d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // b) The first packet contains only the header. The initiator (MTP host) needs 724d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono // to remember which way the responder used, and send upcoming data in the same way. 725d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono ALOGD("Found short packet that contains only a header."); 726d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER; 727d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono } 728b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialData) { 729b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood if (initialDataLength > 0) { 7304fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (!callback(initialData, offset, initialDataLength, clientData)) { 73181ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono ALOGE("Failed to write initial data."); 73281ca5ade77ea518aa21fdd7434d2db5df088a115Daichi Hirono writingError = true; 73331c52e7c8c01e1db6ff9bcf66135c72544b1235aKenny Root } 7344fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono offset += initialDataLength; 7350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 736b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood free(initialData); 7370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7384fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 7390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 7404fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono // USB reads greater than 16K don't work. 7414fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE]; 7424fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono mRequestIn1->buffer = buffer1; 7434fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono mRequestIn2->buffer = buffer2; 7444fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono struct usb_request* req = NULL; 7454fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono 7464fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono while (offset < length) { 7474fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono // Wait for previous read to complete. 74842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood void* writeBuffer = NULL; 749b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood int writeLength = 0; 7504fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (req) { 7514fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono const int read = mData.readDataWait(mDevice); 7524fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (read < 0) { 7534fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("readDataWait failed."); 7544fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return false; 7550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 7564fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono writeBuffer = req->buffer; 7574fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono writeLength = read; 7584fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 7590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 7604fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono // Request to read next chunk. 7614fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono const uint32_t nextOffset = offset + writeLength; 7624fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (nextOffset < length) { 7634fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono // Queue up a read request. 7644fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono const size_t remaining = length - nextOffset; 7654fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1); 7664a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono req->buffer_length = remaining > MTP_BUFFER_SIZE ? 7674a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono static_cast<size_t>(MTP_BUFFER_SIZE) : remaining; 7684fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (mData.readDataAsync(req) != 0) { 7694fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("readDataAsync failed"); 7704fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono return false; 771b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7724fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono } 7730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood 7744fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono // Write previous buffer. 7754fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (writeBuffer && !writingError) { 7764fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono if (!callback(writeBuffer, offset, writeLength, clientData)) { 7774fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono ALOGE("write failed"); 7784fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono writingError = true; 779b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 780b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood } 7814fd9a8b9865addfedbcd84d5c9efea0f647086a0Daichi Hirono offset = nextOffset; 7820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood } 783b9ff444a7eaf7ffd43970c0477110c6808bd4a7cMike Lockwood 7844a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono if (writtenSize) { 7854a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono *writtenSize = length; 7864a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono } 7874a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono 7884a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return readResponse() == MTP_RESPONSE_OK; 7894a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono} 7904a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono 7914a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hironobool MtpDevice::readPartialObject(MtpObjectHandle handle, 7924a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono uint32_t offset, 7934a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono uint32_t size, 7944a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono uint32_t *writtenSize, 7954a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono ReadObjectCallback callback, 7964a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono void* clientData) { 7974a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono Mutex::Autolock autoLock(mMutex); 7984a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono 7994a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono mRequest.reset(); 8004a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono mRequest.setParameter(1, handle); 8014a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono mRequest.setParameter(2, offset); 8024a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono mRequest.setParameter(3, size); 8034a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT)) { 8044a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono ALOGE("Failed to send a read request."); 8054a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono return false; 8064a7cea889d81bbf8f555df006fe384a405b3ba53Daichi Hirono } 807610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // The expected size is null because it requires the exact number of bytes to read though 808610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // MTP_OPERATION_GET_PARTIAL_OBJECT allows devices to return shorter length of bytes than 809610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // requested. Destination's buffer length should be checked in |callback|. 810326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono return readData(callback, nullptr /* expected size */, writtenSize, clientData); 811326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono} 812326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono 813326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hironobool MtpDevice::readPartialObject64(MtpObjectHandle handle, 814326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono uint64_t offset, 815326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono uint32_t size, 816326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono uint32_t *writtenSize, 817326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono ReadObjectCallback callback, 818326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono void* clientData) { 819326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono Mutex::Autolock autoLock(mMutex); 820326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono 821326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono mRequest.reset(); 822326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono mRequest.setParameter(1, handle); 823326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono mRequest.setParameter(2, 0xffffffff & offset); 824326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono mRequest.setParameter(3, 0xffffffff & (offset >> 32)); 825326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono mRequest.setParameter(4, size); 826326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT_64)) { 827326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono ALOGE("Failed to send a read request."); 828326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono return false; 829326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono } 830610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // The expected size is null because it requires the exact number of bytes to read though 831610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // MTP_OPERATION_GET_PARTIAL_OBJECT_64 allows devices to return shorter length of bytes than 832610d4a125f0144ec4915e5cef9f53e431cb117afDaichi Hirono // requested. Destination's buffer length should be checked in |callback|. 833326edd98bbc52d41de6e0943ca8a343228ed87a5Daichi Hirono return readData(callback, nullptr /* expected size */, writtenSize, clientData); 8340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood} 835a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood 8365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) { 8373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation)); 838f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 8395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setOperationCode(operation); 8405ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (mTransactionID > 0) 8415ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.setTransactionID(mTransactionID++); 84242d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mRequest.write(mRequestOut); 8435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mRequest.dump(); 8445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return (ret > 0); 8455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() { 8483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendData\n"); 8495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 8505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 851d95d34d49d36a2f27212485c79cde769af3873e9Daichi Hirono int ret = mData.write(mRequestOut, mPacketDivisionMode); 8525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 85364c948bf5041fdfe391553315c9d028e1ee56382Tomasz Mikolajewski return (ret >= 0); 8545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() { 8575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.reset(); 85842d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mData.read(mRequestIn1); 8593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readData returned %d\n", ret); 8605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 861f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) { 862b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("got response packet instead of data packet"); 863f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // we got a response packet rather than data 864f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood // copy it to mResponse 865f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mResponse.copyFrom(mData); 866f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = true; 867f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return false; 868f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 8695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mData.dump(); 8705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return true; 8715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood else { 8733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse failed\n"); 8745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return false; 8755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8785ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() { 8793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readResponse\n"); 880f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood if (mReceivedResponse) { 881f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood mReceivedResponse = false; 882f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood return mResponse.getResponseCode(); 883f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } 88442d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwood int ret = mResponse.read(mRequestIn1); 8853d74457b66533b170606347e60628e55a2af255eMike Lockwood // handle zero length packets, which might occur if the data transfer 8863d74457b66533b170606347e60628e55a2af255eMike Lockwood // ends on a packet boundary 8873d74457b66533b170606347e60628e55a2af255eMike Lockwood if (ret == 0) 8883d74457b66533b170606347e60628e55a2af255eMike Lockwood ret = mResponse.read(mRequestIn1); 8895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood if (ret >= MTP_CONTAINER_HEADER_SIZE) { 8905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood mResponse.dump(); 8915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return mResponse.getResponseCode(); 892f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood } else { 893b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("readResponse failed\n"); 8945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood return -1; 8955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood } 8965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} 8975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood 8988a7ffae09a019de7109b30c505561c453910bde1Daichi Hironoint MtpDevice::submitEventRequest() { 8998a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono if (mEventMutex.tryLock()) { 9008a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono // An event is being reaped on another thread. 9018a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono return -1; 9028a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono } 9038a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono if (mProcessingEvent) { 9048a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono // An event request was submitted, but no reapEventRequest called so far. 9058a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono return -1; 9068a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono } 9078a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono Mutex::Autolock autoLock(mEventMutexForInterrupt); 9088a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mEventPacket.sendRequest(mRequestIntr); 9098a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono const int currentHandle = ++mCurrentEventHandle; 9108a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mProcessingEvent = true; 9118a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mEventMutex.unlock(); 9128a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono return currentHandle; 9138a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono} 9148a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono 91559a90609cc340d2933c119aa47045a5c95530b48Daichi Hironoint MtpDevice::reapEventRequest(int handle, uint32_t (*parameters)[3]) { 9168a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono Mutex::Autolock autoLock(mEventMutex); 91759a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono if (!mProcessingEvent || mCurrentEventHandle != handle || !parameters) { 9188a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono return -1; 9198a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono } 9208a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono mProcessingEvent = false; 9218a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono const int readSize = mEventPacket.readResponse(mRequestIntr->dev); 9228a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono const int result = mEventPacket.getEventCode(); 92359a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono // MTP event has three parameters. 92459a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono (*parameters)[0] = mEventPacket.getParameter(1); 92559a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono (*parameters)[1] = mEventPacket.getParameter(2); 92659a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono (*parameters)[2] = mEventPacket.getParameter(3); 92759a90609cc340d2933c119aa47045a5c95530b48Daichi Hirono return readSize != 0 ? result : 0; 9288a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono} 9298a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono 9308a7ffae09a019de7109b30c505561c453910bde1Daichi Hironovoid MtpDevice::discardEventRequest(int handle) { 9318a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono Mutex::Autolock autoLock(mEventMutexForInterrupt); 9328a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono if (mCurrentEventHandle != handle) { 9338a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono return; 9348a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono } 9358a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono usb_request_cancel(mRequestIntr); 9368a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono} 9378a7ffae09a019de7109b30c505561c453910bde1Daichi Hirono 9385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood} // namespace android 939