MtpDevice.cpp revision e3e76c456baee122de6715ae280130abaddc906c
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
415ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::MtpDevice(struct usb_device* device, int interface,
425ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood            struct usb_endpoint *ep_in, struct usb_endpoint *ep_out,
435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood            struct usb_endpoint *ep_intr)
445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    :   mDevice(device),
455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mInterface(interface),
465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mEndpointIn(ep_in),
475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mEndpointOut(ep_out),
485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mEndpointIntr(ep_intr),
495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDeviceInfo(NULL),
505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mID(usb_device_get_unique_id(device)),
515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mSessionID(0),
525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mTransactionID(0)
535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood{
545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
555ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
565ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDevice::~MtpDevice() {
575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    close();
58a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    for (int i = 0; i < mDeviceProperties.size(); i++)
59a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        delete mDeviceProperties[i];
605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::initialize() {
635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    openSession();
645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mDeviceInfo = getDeviceInfo();
655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDeviceInfo) {
665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDeviceInfo->print();
67a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
68a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        if (mDeviceInfo->mDeviceProperties) {
69a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            int count = mDeviceInfo->mDeviceProperties->size();
70a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            for (int i = 0; i < count; i++) {
71a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
72a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                MtpProperty* property = getDevicePropDesc(propCode);
73a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                if (property) {
74a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                    property->print();
75a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                    mDeviceProperties.push(property);
76a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood                }
77a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood            }
78a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        }
795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodvoid MtpDevice::close() {
835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice) {
845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_release_interface(mDevice, mInterface);
855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        usb_device_close(mDevice);
865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mDevice = NULL;
875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodconst char* MtpDevice::getDeviceName() {
915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mDevice)
925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return usb_device_get_name(mDevice);
935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else
945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return "???";
955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::openSession() {
980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = 0;
1015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 0;
1025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpSessionID newSession = 1;
1035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, newSession);
1055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
1065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
1075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
1085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
1095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        newSession = mResponse.getParameter(1);
1105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else if (ret != MTP_RESPONSE_OK)
1115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
1125ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1135ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mSessionID = newSession;
1145ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mTransactionID = 1;
1155ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
1165ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1175ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1185ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::closeSession() {
1195ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    // FIXME
1205ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return true;
1215ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1225ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1235ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpDeviceInfo* MtpDevice::getDeviceInfo() {
1240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
1250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1265ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1275ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
1285ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1295ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
1305ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1315ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
1325ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
1335ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpDeviceInfo* info = new MtpDeviceInfo;
1345ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        info->read(mData);
1355ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return info;
1365ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
1375ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
1385ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1395ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1405ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageIDList* MtpDevice::getStorageIDs() {
1410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
1420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1435ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
1455ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
1475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
1495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
1505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
1515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
1525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
1535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1545ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1555ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
1560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
1570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
1605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
1615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
1635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
1655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
1665ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpStorageInfo* info = new MtpStorageInfo(storageID);
1675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        info->read(mData);
1685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return info;
1695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
1705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
1715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1725ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1735ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
1745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood            MtpObjectFormat format, MtpObjectHandle parent) {
1750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
1760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1775ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1785ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, storageID);
1795ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(2, format);
1805ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(3, parent);
1815ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
1825ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1835ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
1845ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
1855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
1865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
1875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mData.getAUInt32();
1885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
1895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
1905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
1915ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
1925ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
1930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
1940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
1956afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    // FIXME - we might want to add some caching here
1966afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
1975ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.reset();
1985ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setParameter(1, handle);
1995ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
2005ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
2015ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (!readData())
2025ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return NULL;
2035ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    MtpResponseCode ret = readResponse();
2045ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret == MTP_RESPONSE_OK) {
2055ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        MtpObjectInfo* info = new MtpObjectInfo(handle);
2065ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        info->read(mData);
2075ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return info;
2085ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
2095ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return NULL;
2105ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
2115ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
2123e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwoodvoid* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
2130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
2140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2153e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.reset();
2163e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    mRequest.setParameter(1, handle);
2173e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
2183e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        MtpResponseCode ret = readResponse();
2193e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
2203e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood            return mData.getData(outLength);
2213e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood        }
2223e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    }
2233e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    outLength = 0;
2243e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood    return NULL;
2256afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
2266afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
2270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike LockwoodMtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
2280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
2290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
2310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpObjectHandle parent = info->mParent;
2320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (parent == 0)
2330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        parent = MTP_PARENT_ROOT;
2340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.setParameter(1, info->mStorageID);
2360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.setParameter(2, info->mParent);
2370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mStorageID);
2390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mFormat);
2400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mProtectionStatus);
2410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mCompressedSize);
2420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mThumbFormat);
2430cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbCompressedSize);
2440cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixWidth);
2450cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mThumbPixHeight);
2460cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixWidth);
2470cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixHeight);
2480cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mImagePixDepth);
2490cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mParent);
2500cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt16(info->mAssociationType);
2510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mAssociationDesc);
2520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putUInt32(info->mSequenceNumber);
2530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(info->mName);
2540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    char created[100], modified[100];
2560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateCreated, created, sizeof(created));
2570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    formatDateTime(info->mDateModified, modified, sizeof(modified));
2580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(created);
2600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.putString(modified);
2610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (info->mKeywords)
2620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putString(info->mKeywords);
2630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    else
2640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mData.putEmptyString();
2650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood   if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
2670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        MtpResponseCode ret = readResponse();
2680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (ret == MTP_RESPONSE_OK) {
2690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mStorageID = mResponse.getParameter(1);
2700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mParent = mResponse.getParameter(2);
2710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            info->mHandle = mResponse.getParameter(3);
2720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            return info->mHandle;
2730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
2740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
2750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (MtpObjectHandle)-1;
2760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
2770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
2790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
2800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int remaining = info->mCompressedSize;
2820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.reset();
2830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mRequest.setParameter(1, info->mHandle);
2840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
2850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        // send data header
2860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
2870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
2880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        char buffer[65536];
2890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        while (remaining > 0) {
2900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int count = read(srcFD, buffer, sizeof(buffer));
2910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            if (count > 0) {
2920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                int written = mData.write(mEndpointOut, buffer, count);
2930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                // FIXME check error
2940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                remaining -= count;
2950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            } else {
2960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                break;
2970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
2980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
2990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
3000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpResponseCode ret = readResponse();
3010cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (remaining == 0 && ret == MTP_RESPONSE_OK);
3020cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
3030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3046afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwoodbool MtpDevice::deleteObject(MtpObjectHandle handle) {
3050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3076afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.reset();
3086afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    mRequest.setParameter(1, handle);
3096afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
3106afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        MtpResponseCode ret = readResponse();
3116afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        if (ret == MTP_RESPONSE_OK)
3126afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood            return true;
3136afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    }
3146afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    return false;
3156afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
3166afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood
3176afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
3186afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
3196afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    if (info)
3206afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return info->mParent;
3216afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    else
3226afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
3236afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood}
3243e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
3256afc41d095ccb159f6c4705bed903b6c048b922aMike LockwoodMtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
3266afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    MtpObjectInfo* info = getObjectInfo(handle);
3276afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    if (info)
3286afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return info->mStorageID;
3296afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood    else
3306afc41d095ccb159f6c4705bed903b6c048b922aMike Lockwood        return -1;
3313e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood}
3323e072b354d1e1e3ee62d58492f0739139df8aff1Mike Lockwood
333a6c490b8b2d96ebaab632286029463f932ae3b6bMike LockwoodMtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
3340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    Mutex::Autolock autoLock(mMutex);
3350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
336a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.reset();
337a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    mRequest.setParameter(1, code);
338a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
339a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
340a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (!readData())
341a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return NULL;
342a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    MtpResponseCode ret = readResponse();
343a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    if (ret == MTP_RESPONSE_OK) {
344a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        MtpProperty* property = new MtpProperty;
345e3e76c456baee122de6715ae280130abaddc906cMike Lockwood        property->read(mData);
346a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        return property;
347a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    }
348a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood    return NULL;
349a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood}
350a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
3510cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodclass ReadObjectThread : public Thread {
3520cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodprivate:
3530cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpDevice*          mDevice;
3540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    MtpObjectHandle     mHandle;
3550cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int                 mObjectSize;
3560cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    void*               mInitialData;
3570cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int                 mInitialDataLength;
3580cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int                 mFD;
3590cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3600cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodpublic:
3610cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    ReadObjectThread(MtpDevice* device, MtpObjectHandle handle, int objectSize)
3620cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        : mDevice(device),
3630cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood          mHandle(handle),
3640cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood          mObjectSize(objectSize),
3650cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood          mInitialData(NULL),
3660cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood          mInitialDataLength(0)
3670cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    {
3680cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
3690cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3700cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    virtual ~ReadObjectThread() {
3710cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (mFD >= 0)
3720cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            close(mFD);
3730cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        free(mInitialData);
3740cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
3750cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3760cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    // returns file descriptor
3770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int init() {
3780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mDevice->mRequest.reset();
3790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mDevice->mRequest.setParameter(1, mHandle);
3800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (mDevice->sendRequest(MTP_OPERATION_GET_OBJECT)
3810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                && mDevice->mData.readDataHeader(mDevice->mEndpointIn)) {
3820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3830cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            // mData will contain header and possibly the beginning of the object data
3840cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            mInitialData = mDevice->mData.getData(mInitialDataLength);
3850cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3860cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            // create a pipe for the client to read from
3870cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int pipefd[2];
3880cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            if (pipe(pipefd) < 0) {
3890cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                LOGE("pipe failed (%s)", strerror(errno));
3900cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                return -1;
3910cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
3920cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
3930cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            mFD = pipefd[1];
3940cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            return pipefd[0];
3950cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        } else {
3960cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood           return -1;
3970cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
3980cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
3990cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4000cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    virtual bool threadLoop() {
4010cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        int remaining = mObjectSize;
4020cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        if (mInitialData) {
4030cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            write(mFD, mInitialData, mInitialDataLength);
4040cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            remaining -= mInitialDataLength;
4050cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            free(mInitialData);
4060cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            mInitialData = NULL;
4070cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
4080cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
409da90dff17b6ce79d0a7d8ab2dbe2aa69cd1c11aaMike Lockwood        char buffer[16384];
4100cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        while (remaining > 0) {
4110cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int readSize = (remaining > sizeof(buffer) ? sizeof(buffer) : remaining);
4120cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int count = mDevice->mData.readData(mDevice->mEndpointIn, buffer, readSize);
4130cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            int written;
4140cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            if (count >= 0) {
4150cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                int written = write(mFD, buffer, count);
4160cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                // FIXME check error
4170cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                remaining -= count;
4180cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            } else {
4190cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood                break;
4200cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood            }
4210cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        }
4220cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4230cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        MtpResponseCode ret = mDevice->readResponse();
4240cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mDevice->mMutex.unlock();
4250cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        return false;
4260cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
4270cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood};
4280cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4290cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    // returns the file descriptor for a pipe to read the object's data
4300cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodint MtpDevice::readObject(MtpObjectHandle handle, int objectSize) {
4310cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mMutex.lock();
4320cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4330cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    ReadObjectThread* thread = new ReadObjectThread(this, handle, objectSize);
4340cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    int fd = thread->init();
4350cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    if (fd < 0) {
4360cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        delete thread;
4370cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        mMutex.unlock();
4380cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    } else {
4390cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood        thread->run("ReadObjectThread");
4400cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    }
4410cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return fd;
4420cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
443a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood
4445ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::sendRequest(MtpOperationCode operation) {
445f43c641bf3f8bcb5748f4ae504d434896edc94f5Mike Lockwood    LOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
4465ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.setOperationCode(operation);
4475ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (mTransactionID > 0)
4485ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mRequest.setTransactionID(mTransactionID++);
4495ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    int ret = mRequest.write(mEndpointOut);
4505ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mRequest.dump();
4515ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return (ret > 0);
4525ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4535ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4540cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::sendData() {
455f43c641bf3f8bcb5748f4ae504d434896edc94f5Mike Lockwood    LOGV("sendData\n");
4565ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setOperationCode(mRequest.getOperationCode());
4575ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.setTransactionID(mRequest.getTransactionID());
4585ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    int ret = mData.write(mEndpointOut);
4595ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.dump();
4605ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    return (ret > 0);
4615ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4625ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4635ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwoodbool MtpDevice::readData() {
4645ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    mData.reset();
4655ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    int ret = mData.read(mEndpointIn);
466f43c641bf3f8bcb5748f4ae504d434896edc94f5Mike Lockwood    LOGV("readData returned %d\n", ret);
4675ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
4685ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mData.dump();
4695ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return true;
4705ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4715ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else {
472f43c641bf3f8bcb5748f4ae504d434896edc94f5Mike Lockwood        LOGV("readResponse failed\n");
4735ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return false;
4745ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4755ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4765ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4770cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwoodbool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
4780cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.setOperationCode(operation);
4790cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    mData.setTransactionID(mRequest.getTransactionID());
4800cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood    return (!mData.writeDataHeader(mEndpointOut, dataLength));
4810cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood}
4820cf89f2e622aa53f31fa5762ca4bc805bb509ed3Mike Lockwood
4835ed68d29a140e14c8d46980fa844548eb33b1e87Mike LockwoodMtpResponseCode MtpDevice::readResponse() {
484f43c641bf3f8bcb5748f4ae504d434896edc94f5Mike Lockwood    LOGV("readResponse\n");
4855ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    int ret = mResponse.read(mEndpointIn);
4865ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
4875ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        mResponse.dump();
4885ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return mResponse.getResponseCode();
4895ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4905ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    else {
491a6c490b8b2d96ebaab632286029463f932ae3b6bMike Lockwood        LOGD("readResponse failed\n");
4925ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood        return -1;
4935ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood    }
4945ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}
4955ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood
4965ed68d29a140e14c8d46980fa844548eb33b1e87Mike Lockwood}  // namespace android
497