MtpServer.cpp revision 3d1d7767afc7c488197ec40a22739159c5110721
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> 2316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <errno.h> 24d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <sys/stat.h> 25d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <dirent.h> 2616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 27c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 28c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 29a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood#define LOG_TAG "MtpServer" 30a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 327f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood#include "MtpObjectInfo.h" 3421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 398065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 4016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 417850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 427850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 5364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MTP_OPERATION_GET_THUMB, 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 63e3e76c456baee122de6715ae280130abaddc906cMike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 70d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT, 7116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 738277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_DESC, 74677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 75677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 76b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_LIST, 77b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_LIST, 78b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, 79b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SEND_OBJECT_PROP_LIST, 80438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 81438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // Android extension for direct file IO 847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT_64, 857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_SEND_PARTIAL_OBJECT, 867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_TRUNCATE_OBJECT, 877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_BEGIN_EDIT_OBJECT, 887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_END_EDIT_OBJECT, 8916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 9016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 92873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 93873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 94a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_ADDED, 95a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_REMOVED, 96873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 97873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 983d1d7767afc7c488197ec40a22739159c5110721Mike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp, 998e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1011865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1023d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mPtp(ptp), 1038e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1048e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1058e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 10616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 10716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1094714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 11116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 117a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 118a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 126a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 127a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 128a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 129a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 130a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 131a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 132a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 133a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 137fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 138fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 140fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 147a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 148a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 149a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 150a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 151a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 152a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("MtpServer::run fd: %d\n", fd); 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 16159d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("request read returned %d, errno: %d", ret, errno); 162916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 163916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 164916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 165916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 171b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 175438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 17916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 182b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("data read returned %d, errno: %d", ret, errno); 183916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 184916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 186916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 18816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 189b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("received data:"); 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 195916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 196916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 199b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending data:"); 20023d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 201916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 202916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 203b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 205916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 212916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 213b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending response %04X", mResponse.getResponseCode()); 214916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21523d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 21616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 217b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 218916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 219916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 221916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 224916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 22521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("skipping response\n"); 22616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2286b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // commit any open edits 2307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 2347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.clear(); 2377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2386b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2396b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 24016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 24116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 242873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 243a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectAdded %d\n", handle); 244a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 245873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 246873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 247873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 248a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectRemoved %d\n", handle); 249a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 250a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 251a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 252a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 253a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreAdded %08X\n", id); 254a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 255a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 257a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 258a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreRemoved %08X\n", id); 259a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 260a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 261a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 262a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 26373ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 264a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 26573ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 266a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 26773ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 26859d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("mEvent.write returned %d\n", ret); 26973ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 270873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 271873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 2727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, 2737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t size, MtpObjectFormat format, int fd) { 274c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd); 2757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.add(edit); 2767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { 2797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 282c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) return edit; 2837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return NULL; 2857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::removeEditObject(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) { 2927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.removeAt(i); 2947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return; 2957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("ObjectEdit not found in removeEditObject"); 2987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::commitEdit(ObjectEdit* edit) { 301c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true); 3027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 305916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 306a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 307a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 30816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 30916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 31016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 31216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 31416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 315b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("expected SendObject after SendObjectInfo"); 31616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 31716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 32416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 341343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 342343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 343343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 344438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 345438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 346438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 347438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 348438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 349438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 35016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 35116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3538277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3598277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3608277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3618277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 365b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 366b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 367b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 37016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 37116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 37216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 37316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 37464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood case MTP_OPERATION_GET_THUMB: 37564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood response = doGetThumb(); 37664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood break; 377d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 3787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT_64: 3797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doGetPartialObject(operation); 380d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 38116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 38216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 38316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 39121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 39221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 393e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 394e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 395e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 3967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_SEND_PARTIAL_OBJECT: 3977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doSendPartialObject(); 3987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 3997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_TRUNCATE_OBJECT: 4007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doTruncateObject(); 4017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_BEGIN_EDIT_OBJECT: 4037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doBeginEditObject(); 4047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_END_EDIT_OBJECT: 4067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doEndEditObject(); 4077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 40816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 409a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation)); 41016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 41116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 414916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 415916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 41616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 417916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 41816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 41916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 422c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 42316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 424782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 425782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 426782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 427782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4303d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4313d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(0); 4323d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4333d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP Vendor Extension ID 4343d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(6); 4353d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4373d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4383d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // no extensions 4393d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set(""); 4403d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4413d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP extensions 4423d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set("microsoft.com: 1.0; android.com: 1.0;"); 4433d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 44416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 44516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 448873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 449873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 450782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 451782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 452782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 4538d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 4548d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 4558d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 45616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 457c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 458c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 459c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 46016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 46116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 463c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 464c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 465c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 46616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 46716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 468782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 469782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 470782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 471782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 47216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 47316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 47416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 47516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 47616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 47716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 48116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 4826b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 4836b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 4846b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 48516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 48616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 48716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 48816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 48916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 4936b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 49516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 49816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 49916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 50016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 50216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 50316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 50416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 50516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 52716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 52816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 53516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 5362e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 537782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 538bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 53916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 546e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 548dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 549a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 550a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 551a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 55216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 55416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 55516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 55616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 55716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 55816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 559343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 560343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 561343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 562343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 563343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 564343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 565dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 566a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 567a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 568343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 569343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 570343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 571343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 572343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 573343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 574343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 575343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 576343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 577343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 578343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 579438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 580438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 581438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 582a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 583a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 584a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 5858277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5868277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 587438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 5888277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 5898277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 5908277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 5918277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 592438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 593438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 594438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 595438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 596438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 597438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 598438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 599438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 600a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 601a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 602438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 603a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 604438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 605438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 606438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 607438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 608438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 609438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 61016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 611a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 612a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 61316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 61416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 61559d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropValue %d %s\n", handle, 6168277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 61716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6188277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 6198277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6208277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6218277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 622a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 623a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 6248277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6258277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 62659d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetObjectPropValue %d %s\n", handle, 6278277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 6288277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6298277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 6308277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6318277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6328277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 6338277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 63459d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropValue %s\n", 6358277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6368277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6378277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 6388277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6398277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6408277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 6418277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 64259d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetDevicePropValue %s\n", 6438277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6448277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6458277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 6468277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6478277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6488277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 6498277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 65059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("ResetDevicePropValue %s\n", 6518277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6528277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6538277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 65416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 65516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 656b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 657a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 658a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 659b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 660b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 66140ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 66240ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 66340ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 664b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 665f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 66659d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 667b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 668b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 669b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 670b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 671b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 672b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 67316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 674a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 675a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 67616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectInfo info(handle); 6787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpResponseCode result = mDatabase->getObjectInfo(handle, info); 6797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result == MTP_RESPONSE_OK) { 6807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood char date[20]; 6817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mStorageID); 6837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mFormat); 6847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mProtectionStatus); 6857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // if object is being edited the database size may be out of date 6877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t size = info.mCompressedSize; 6887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 6897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit) 690c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize); 6917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(size); 6927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mThumbFormat); 6947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbCompressedSize); 6957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixWidth); 6967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixHeight); 6977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixWidth); 6987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixHeight); 6997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixDepth); 7007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mParent); 7017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mAssociationType); 7027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mAssociationDesc); 7037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mSequenceNumber); 7047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(info.mName); 7057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // date created 7067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood formatDateTime(info.mDateModified, date, sizeof(date)); 7077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(date); // date modified 7087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // keywords 7097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 7107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 71116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 71216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 71316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 714a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 715a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 71616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 717c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 71816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 719fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 720fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 7219c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7229c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 72316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7249c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 72516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 726c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 727c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 728c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 729c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 73016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 73116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 73216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // send data header 73416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 73516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 73623d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE); 73716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 73916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 740c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 741916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 742916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 743916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 744916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 745916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 746916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 74716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 74816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 74916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 75064000788211f4c7e78c80a4a155390d1316e1176Mike LockwoodMtpResponseCode MtpServer::doGetThumb() { 75164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 75264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood size_t thumbSize; 75364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood void* thumb = mDatabase->getThumbnail(handle, thumbSize); 75464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood if (thumb) { 75564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood // send data 75664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 75764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 75864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.writeData(mFD, thumb, thumbSize); 75964000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood free(thumb); 76064000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_OK; 76164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } else { 76264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 76364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } 76464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood} 76564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood 7667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { 767a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 768a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 769d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 7707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset; 7717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length; 7727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = mRequest.getParameter(2); 7737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { 7747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // android extension with 64 bit offset 7757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 7767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 7777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(4); 7787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 7797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // standard GetPartialObject 7807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(3); 7817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 782d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 783d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 784fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 785fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 786d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 787d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 788d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (offset + length > fileLength) 789d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 790d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 791d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 792d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 793d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 794d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 795d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 796d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 797d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 798d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 799d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 800d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 801d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // send data header 802d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 803d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 804d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE); 805d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 806d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // then transfer the file 807d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 808d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 809d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 810d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 811d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 812d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 813d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 814d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 815d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 816d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 817d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 81816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 81916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 82016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 82116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 82216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 82316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 82416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 82516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 82616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 8271865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 82816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 8291865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 8301865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 831fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 832fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 833fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 8349c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 8359c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 836fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 837fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 83816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 83916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 84116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 84216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 84316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 84416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 84516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 84616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 84716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 84816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 84916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 85016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 85116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 85216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 85316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 85416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 85516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 85616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 85716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 85816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 85916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 86016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 86116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 86259d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("name: %s format: %04X\n", (const char *)name, format); 863fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 86416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 86516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 86616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 86716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 86816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 86916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 87016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 87120c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 87220c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 87320c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 87420c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 875a849440ca96e93f700d62c6e41d48905b4d405b6Mike LockwoodLOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 8764714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 8774714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 878fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 87916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 880fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 88116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 88316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 8848e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 88516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 88616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 88716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 8888e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 889aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 890aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 891aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 89216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 89316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 89416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 89516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 8964714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 89716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 89816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 89916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 9008277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 90116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 90216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 90416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 90516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 907a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 908a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9094714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 9104714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 9114714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood int ret; 9124714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 91316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 914b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("Expected SendObjectInfo before SendObject"); 9154714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 9164714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 91716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 91816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read the header 9204714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood ret = mData.readDataHeader(mFD); 92116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 92216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // reset so we don't attempt to send this back 92416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 92516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 927c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); 928c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 9294714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 9304714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 931c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 9328e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 9338e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 9344714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 9358e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 9368e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 9378e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 93816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 93916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = mSendObjectFileSize; 94016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 94159d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("receiving %s\n", (const char *)mSendObjectFilePath); 94216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // transfer the file 94316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 944c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 9458e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 946b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 94716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 948916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 949916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 950916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 9514714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 952916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 9534714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 954916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 9554714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 9564714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 9574714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 958aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 9594714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 9604714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 9614714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 96216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 96316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 964d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 965d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 966d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathLength = strlen(path); 967d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 968d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path too long: %s\n", path); 969d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 970d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 971d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 972d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 973d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 974d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 975d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 976d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 977d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 978d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 979d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("opendir %s failed: %s", path, strerror(errno)); 980d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 981d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 982d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 983d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 984d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 985d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 986d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 987d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 988d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 989d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 990d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 991d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 992d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 993d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 994d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path %s/%s too long\n", path, name); 995d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 996d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 997d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 998d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 999d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 1000d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 1001d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 1002d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 1003d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1004d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 1005d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1006d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 10077ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 1008d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1009d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1010d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 1011d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 1012d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 1013d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 1014d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 1015d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 1016d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1017d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 1018d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1019d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1020d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 1021d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1022d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1023d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 102416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 1025a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 1026a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 102716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 1028d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 102916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 103016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 103116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 103216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 103316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 1034fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 10359c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 10369c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood LOGV("deleting %s", (const char *)filePath); 1037d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deletePath((const char *)filePath); 10389c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return mDatabase->deleteFile(handle); 10399c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } else { 10409c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 10419c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 104216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 104316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 104416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 104521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 104616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 104759d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 10488277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 10498277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 105021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 105121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 10528277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 10538277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 10548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 10558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 105616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 10578277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 10588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 105959d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 10608277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 10618277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 10628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 106321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 10648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 106521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 106616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10677850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 10687d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doSendPartialObject() { 10697d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!hasStorage()) 10707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 10717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 10727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 10737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 10747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 10757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length = mRequest.getParameter(4); 10767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 10787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 10797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doSendPartialObject"); 10807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 10817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // can't start writing past the end of the file 1084c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (offset > edit->mSize) { 1085c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood LOGD("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize); 10867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 10877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // read the header 10907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int ret = mData.readDataHeader(mFD); 10917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // FIXME - check for errors here. 10927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // reset so we don't attempt to send this back 10947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.reset(); 10957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1096c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood const char* filePath = (const char *)edit->mPath; 10977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGV("receiving partial %s %lld %ld\n", filePath, offset, length); 10987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mtp_file_range mfr; 1099c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood mfr.fd = edit->mFD; 11007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mfr.offset = offset; 11017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mfr.length = length; 11027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // transfer the file 11047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 11057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 11067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ret < 0) { 11077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, 0); 11087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (errno == ECANCELED) 11097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 11107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood else 11117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, length); 11147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t end = offset + length; 1115c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (end > edit->mSize) { 1116c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = end; 11177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doTruncateObject() { 11227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 11257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doTruncateObject"); 11267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset |= (offset2 << 32); 1132c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (ftruncate(edit->mFD, offset) != 0) { 11337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 1135c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = offset; 11367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11407d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doBeginEditObject() { 11417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (getEditObject(handle)) { 11437d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object already open for edit in doBeginEditObject"); 11447d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11457d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpString path; 11487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int64_t fileLength; 11497d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectFormat format; 11507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); 11517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result != MTP_RESPONSE_OK) 11527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 11537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int fd = open((const char *)path, O_RDWR | O_EXCL); 11557d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (fd < 0) { 11567d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); 11577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11587d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11597d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11607d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood addEditObject(handle, path, fileLength, format, fd); 11617d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11627d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11637d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11647d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doEndEditObject() { 11657d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11677d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 11687d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doEndEditObject"); 11697d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 11737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood removeEditObject(handle); 11747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11777850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 1178