MtpServer.cpp revision dcd89ecad321e2e052322fe2b1907d50d762b311
116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/* 216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License. 616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at 716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and 1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License. 1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */ 1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h> 1816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdlib.h> 1916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/types.h> 2016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/ioctl.h> 2116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/stat.h> 2216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <fcntl.h> 23db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn#include <inttypes.h> 2416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <errno.h> 25d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <sys/stat.h> 26d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <dirent.h> 2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 28c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 29c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 30a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood#define LOG_TAG "MtpServer" 31a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood 3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 337f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood#include "MtpObjectInfo.h" 3521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 408065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 4116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 427850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 437850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 5464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MTP_OPERATION_GET_THUMB, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 64e3e76c456baee122de6715ae280130abaddc906cMike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 678277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 7016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 71d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT, 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_DESC, 75677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 76677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 77b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_LIST, 78b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_LIST, 79b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, 80b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SEND_OBJECT_PROP_LIST, 81438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 82438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // Android extension for direct file IO 857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT_64, 867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_SEND_PARTIAL_OBJECT, 877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_TRUNCATE_OBJECT, 887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_BEGIN_EDIT_OBJECT, 897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_END_EDIT_OBJECT, 9016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 9116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 93873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 94873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 95a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_ADDED, 96a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_REMOVED, 970fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood MTP_EVENT_DEVICE_PROP_CHANGED, 98873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 99873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 1003d1d7767afc7c488197ec40a22739159c5110721Mike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp, 1018e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 10216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1031865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1043d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mPtp(ptp), 1058e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1068e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1078e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 10916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1114714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 11716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 126a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 127a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 128a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 1293ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mStorages.size(); i++) { 130a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 131a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 132a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 133a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 134a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 135a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 139fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 140fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 1413ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mStorages.size(); i++) { 142fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 149a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 150a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 151a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 152a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 153a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 154a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MtpServer::run fd: %d\n", fd); 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 1633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("request read returned %d, errno: %d", ret, errno); 164916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 165916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 166916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 167916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 177438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 18216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 18429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("data read returned %d, errno: %d", ret, errno); 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 186916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 187916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 188916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 1913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("received data:"); 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 199916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 200916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 2013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending data:"); 20223d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 203916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 20529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 211916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 212916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 214916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 2153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending response %04X", mResponse.getResponseCode()); 216916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21723d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 21816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 21929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 221916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 222916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 223916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 226916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 2273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipping response\n"); 22816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2306b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // commit any open edits 2327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 2367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.clear(); 2397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2406b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2416b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 242dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood close(fd); 243dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood mFD = -1; 24416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 24516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 246873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 2473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectAdded %d\n", handle); 248a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 249873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 250873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 251873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 2523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectRemoved %d\n", handle); 253a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 254a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 255a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 2573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreAdded %08X\n", id); 258a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 259a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 260a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 261a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 2623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreRemoved %08X\n", id); 263a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 264a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 265a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 2660fa848d780cf990a2860637f40432d28594c85a3Mike Lockwoodvoid MtpServer::sendDevicePropertyChanged(MtpDeviceProperty property) { 2670fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood ALOGV("sendDevicePropertyChanged %d\n", property); 2680fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood sendEvent(MTP_EVENT_DEVICE_PROP_CHANGED, property); 2690fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood} 2700fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood 271a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 27273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 273a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 27473ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 275a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 27673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 2773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mEvent.write returned %d\n", ret); 27873ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 279873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 280873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 2817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, 2827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t size, MtpObjectFormat format, int fd) { 283c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd); 2847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.add(edit); 2857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { 2887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 291c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) return edit; 2927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return NULL; 2947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::removeEditObject(MtpObjectHandle handle) { 2977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 300c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) { 3017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 3027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.removeAt(i); 3037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return; 3047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 3057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 30629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("ObjectEdit not found in removeEditObject"); 3077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::commitEdit(ObjectEdit* edit) { 310c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true); 3117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 314916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 315a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 316a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 31716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 32429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("expected SendObject after SendObjectInfo"); 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 328dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen int containertype = mRequest.getContainerType(); 329dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (containertype != MTP_CONTAINER_TYPE_COMMAND) { 330dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("wrong container type %d", containertype); 331dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen return false; 332dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 333dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 334dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("got command %s (%x)", MtpDebug::getOperationCodeName(operation), operation); 335dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 34116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 34516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 34716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 34816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 35016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 35116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 35516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 35616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 35716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 358343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 359343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 360343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 361438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 362438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 363438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 364438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 365438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 366438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 36716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3728277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3738277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3758277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3818277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 382b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 383b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 384b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 39164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood case MTP_OPERATION_GET_THUMB: 39264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood response = doGetThumb(); 39364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood break; 394d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 3957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT_64: 3967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doGetPartialObject(operation); 397d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 39816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 39916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 40016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 40216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 40316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 40516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 40616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 40821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 40921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 410e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 411e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 412e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 4137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_SEND_PARTIAL_OBJECT: 4147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doSendPartialObject(); 4157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4167d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_TRUNCATE_OBJECT: 4177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doTruncateObject(); 4187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_BEGIN_EDIT_OBJECT: 4207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doBeginEditObject(); 4217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_END_EDIT_OBJECT: 4237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doEndEditObject(); 4247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 426dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("got unsupported command %s (%x)", 427dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen MtpDebug::getOperationCodeName(operation), operation); 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 432916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 433916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 435916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 43916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 440c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 44116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 442782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 443782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 444782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 445782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4483d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4493d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(0); 4503d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4513d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP Vendor Extension ID 4523d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(6); 4533d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 45416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4553d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4563d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // no extensions 4573d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set(""); 4583d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4593d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP extensions 4603d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set("microsoft.com: 1.0; android.com: 1.0;"); 4613d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 46516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 466873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 467873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 468782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 469782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 470782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 4718d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 4728d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 4738d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 47416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 475c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 476c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 477c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 481c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 482c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 483c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 48416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 48516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 486782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 487782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 488782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 489782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 49516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 49816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 49916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 5006b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 5016b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 5026b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 50316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 50416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 50516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 5116b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 52816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 53516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 53616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 53816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 53916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 54816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 54916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 55116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 55216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 55316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 5542e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 555782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 556bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 55716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 55816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 55916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 56016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 56116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 56216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 56316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 564e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 56516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 566dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 567a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 568a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 569a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 57016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 57116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 57216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 57316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 57416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 57516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 57616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 577343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 578343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 579343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 580343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 581343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 582343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 583dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 584a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 585a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 586343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 587343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 588343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 589343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 590343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 591343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 592343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 593343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 594343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 595343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 596343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 597438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 598438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 599438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 600a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 601a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 602a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6038277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6048277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 605438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 6068277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 6078277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 6088277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 6098277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 610438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 611438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 612438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 613438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 614438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 615438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 616438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 617438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 618a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 619a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 620438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 621a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 622438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 623438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 624438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 625438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 626438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 627438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 62816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 629a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 630a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 63116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 63216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropValue %d %s\n", handle, 6348277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 63516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6368277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 6378277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6388277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6398277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 640a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 641a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 6428277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6438277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetObjectPropValue %d %s\n", handle, 6458277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 6468277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6478277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 6488277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6498277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6508277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 6518277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropValue %s\n", 6538277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 6568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6588277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 6598277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetDevicePropValue %s\n", 6618277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 6648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6668277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 6678277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ResetDevicePropValue %s\n", 6698277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 67216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 67316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 674b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 675a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 676a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 677b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 678b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 67940ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 68040ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 68140ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 682b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 683f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 6843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 685b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 686b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 687b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 688b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 689b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 690b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 69116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 692a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 693a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 69416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectInfo info(handle); 6967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpResponseCode result = mDatabase->getObjectInfo(handle, info); 6977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result == MTP_RESPONSE_OK) { 6987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood char date[20]; 6997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mStorageID); 7017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mFormat); 7027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mProtectionStatus); 7037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // if object is being edited the database size may be out of date 7057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t size = info.mCompressedSize; 7067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 7077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit) 708c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize); 7097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(size); 7107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mThumbFormat); 7127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbCompressedSize); 7137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixWidth); 7147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixHeight); 7157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixWidth); 7167d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixHeight); 7177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixDepth); 7187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mParent); 7197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mAssociationType); 7207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mAssociationDesc); 7217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mSequenceNumber); 7227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(info.mName); 723ec24fa46443634cd29627182c5812ccf43682692Mike Lockwood formatDateTime(info.mDateCreated, date, sizeof(date)); 724ec24fa46443634cd29627182c5812ccf43682692Mike Lockwood mData.putString(date); // date created 7257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood formatDateTime(info.mDateModified, date, sizeof(date)); 7267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(date); // date modified 7277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // keywords 7287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 7297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 73016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 73116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 733a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 734a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 73516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 736c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 73716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 738fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 739fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 7409c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7419c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 74216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7439c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 74416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 745c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 746c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 747c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 748c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 74916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 75016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 751ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 752ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 75316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 75416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 755ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 7563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 757c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 758916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 759916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 760916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 761916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 762916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 763916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 76416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 76516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 76616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 76764000788211f4c7e78c80a4a155390d1316e1176Mike LockwoodMtpResponseCode MtpServer::doGetThumb() { 76864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 76964000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood size_t thumbSize; 77064000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood void* thumb = mDatabase->getThumbnail(handle, thumbSize); 77164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood if (thumb) { 77264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood // send data 77364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 77464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 77564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.writeData(mFD, thumb, thumbSize); 77664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood free(thumb); 77764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_OK; 77864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } else { 77964000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 78064000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } 78164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood} 78264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood 7837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { 784a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 785a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 786d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 7877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset; 7887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length; 7897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = mRequest.getParameter(2); 7907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { 7917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // android extension with 64 bit offset 7927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 7937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 7947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(4); 7957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 7967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // standard GetPartialObject 7977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(3); 7987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 799d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 800d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 801fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 802fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 803d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 804d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 805d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (offset + length > fileLength) 806d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 807d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 808d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 809d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 810d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 811d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 812d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 813d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 814d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 815d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 816ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 817ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 818d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 819d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 820ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // transfer the file 821ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 8223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 823d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 824d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 825d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 826d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 827d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 828d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 829d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 830d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 831d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 832d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 83316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 83416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 83516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 83616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 83716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 83816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 83916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 84016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 8421865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 84316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 8441865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 8451865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 846fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 847fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 848fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 8499c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 8509c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 851fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 852fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 85316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 85416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 85516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 85616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 85716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 85816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 85916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 86016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 86116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 86216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 86316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 86416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 86516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 86616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 86716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 86816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 86916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 87016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 87116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 87216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 87316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 87416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 87516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 87616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 8773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("name: %s format: %04X\n", (const char *)name, format); 878fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 87916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 88016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 88116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 88316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 88416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 88516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88620c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 88720c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 88820c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 8899b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood uint64_t maxFileSize = storage->getMaxFileSize(); 8909b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // check storage max file size 8919b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (maxFileSize != 0) { 8929b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size 8939b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // is >= 0xFFFFFFFF 8949b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF) 8959b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood return MTP_RESPONSE_OBJECT_TOO_LARGE; 8969b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood } 89720c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 898b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 8994714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 9004714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 901fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 90216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 903fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 90416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 90616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 9078e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 90816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 90916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 91016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9118e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 912aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 913aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 914aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 91516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 91616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 91716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 91816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 9194714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 92016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 92116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 9238277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 92416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 92516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 92716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 92816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 930a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 931a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9324714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 9334714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 934ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret, initialData; 9354714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 93616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 93729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Expected SendObjectInfo before SendObject"); 9384714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 9394714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 94016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 94116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 942ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 943ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = mData.read(mFD); 944ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) { 945ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 946ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood goto done; 947ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 948ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood initialData = ret - MTP_CONTAINER_HEADER_SIZE; 94916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 95016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 951af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 952c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 9534714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 9544714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 955c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 9568e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 9578e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 9584714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 9598e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 9608e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 9618e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 962dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (initialData > 0) { 963ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = write(mfr.fd, mData.getData(), initialData); 964dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 96516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 966dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (ret < 0) { 967dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("failed to write initial data"); 968dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen result = MTP_RESPONSE_GENERAL_ERROR; 969dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 970dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (mSendObjectFileSize - initialData > 0) { 971dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.offset = initialData; 972dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (mSendObjectFileSize == 0xFFFFFFFF) { 973dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // tell driver to read until it receives a short packet 974dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = 0xFFFFFFFF; 975dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 976dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = mSendObjectFileSize - initialData; 977dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 9788e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 979dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("receiving %s\n", (const char *)mSendObjectFilePath); 980dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // transfer the file 981dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 982dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("MTP_RECEIVE_FILE returned %d\n", ret); 983dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 984ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 985ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood close(mfr.fd); 98616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 987916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 988916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 989916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 9904714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 991916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 9924714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 993916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 9944714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 9954714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 996ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send the data back 997ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 998ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 9994714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 1000aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 10014714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 10024714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 10034714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 100416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 100516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1006d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 1007d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 1008d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathLength = strlen(path); 1009d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 101029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path too long: %s\n", path); 1011d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1012d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 1013d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 1014d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 1015d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1016d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 1017d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 1018d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1019d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 1020d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 102129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("opendir %s failed: %s", path, strerror(errno)); 1022d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 1023d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1024d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1025d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 1026d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 1027d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 1028d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1029d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 1030d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 1031d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1032d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1033d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1034d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 1035d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 103629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path %s/%s too long\n", path, name); 1037d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1038d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1039d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 1040d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1041d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 1042d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 1043d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 1044d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 1045d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1046d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 1047d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1048d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 10497ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 1050d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1051d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1052d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 1053d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 1054d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 1055d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 1056d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 1057d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 1058d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1059d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 1060d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1061d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 106229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 1063d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1064d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1065d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 106616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 1067a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 1068a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 106916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 1070d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 107116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 107216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 107316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 107416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 107516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 1076fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 10779c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 10783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("deleting %s", (const char *)filePath); 1079a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood result = mDatabase->deleteFile(handle); 1080a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood // Don't delete the actual files unless the database deletion is allowed 1081a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood if (result == MTP_RESPONSE_OK) { 1082a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood deletePath((const char *)filePath); 1083a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood } 10849c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 1085a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood 1086a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood return result; 108716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 108816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 108916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 109021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 109116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 10923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 10938277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 10948277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 109521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 109621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 10978277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 10988277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 10998277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 11008277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 110116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11028277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 11038277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 11043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 11058277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 11068277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 11078277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 110821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 11098277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 111021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 111116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11127850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 11137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doSendPartialObject() { 11147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!hasStorage()) 11157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 11167d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 11207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length = mRequest.getParameter(4); 11217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 112429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doSendPartialObject"); 11257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // can't start writing past the end of the file 1129c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (offset > edit->mSize) { 1130b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize); 11317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1134ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood const char* filePath = (const char *)edit->mPath; 1135db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn ALOGV("receiving partial %s %lld %" PRIu32 "\n", filePath, offset, length); 11367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1137ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 1138ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = mData.read(mFD); 1139ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) 1140ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 1141ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int initialData = ret - MTP_CONTAINER_HEADER_SIZE; 11427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1143ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (initialData > 0) { 11440a694951c00f2135c8968fd2205f71899997a8adMike Lockwoood ret = pwrite(edit->mFD, mData.getData(), initialData, offset); 1145ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood offset += initialData; 1146ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood length -= initialData; 1147ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 11487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1149dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (ret < 0) { 1150dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("failed to write initial data"); 1151dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 1152dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (length > 0) { 1153dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mtp_file_range mfr; 1154dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.fd = edit->mFD; 1155dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.offset = offset; 1156dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = length; 1157dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 1158dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // transfer the file 1159dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 1160dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("MTP_RECEIVE_FILE returned %d", ret); 1161dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 1162ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 11637d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ret < 0) { 11647d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, 0); 11657d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (errno == ECANCELED) 11667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 11677d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood else 11687d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11697d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 1170ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 1171ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send this back 1172ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 11737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, length); 11747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t end = offset + length; 1175c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (end > edit->mSize) { 1176c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = end; 11777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doTruncateObject() { 11827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 118529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doTruncateObject"); 11867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset |= (offset2 << 32); 1192c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (ftruncate(edit->mFD, offset) != 0) { 11937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 1195c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = offset; 11967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doBeginEditObject() { 12017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 12027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (getEditObject(handle)) { 120329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object already open for edit in doBeginEditObject"); 12047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpString path; 12087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int64_t fileLength; 12097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectFormat format; 12107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); 12117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result != MTP_RESPONSE_OK) 12127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 12137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int fd = open((const char *)path, O_RDWR | O_EXCL); 12157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (fd < 0) { 121629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); 12177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood addEditObject(handle, path, fileLength, format, fd); 12217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doEndEditObject() { 12257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 12267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 12277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 122829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doEndEditObject"); 12297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 12337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood removeEditObject(handle); 12347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12377850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 1238