MtpServer.cpp revision 7d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0
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, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike 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 981865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, 998e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1011865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1028e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1038e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1048e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 10516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 10616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 10716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1084714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 10916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 11116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 116a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 117a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 118a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 126a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 127a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 128a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 129a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 130a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 131a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 132a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 136fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 137fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 139fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 146a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 147a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 148a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 149a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 150a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 151a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("MtpServer::run fd: %d\n", fd); 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 16059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("request read returned %d, errno: %d", ret, errno); 161916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 162916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 163916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 164916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 170b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 174438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1758277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 17816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 17916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 181b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("data read returned %d, errno: %d", ret, errno); 182916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 183916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 184916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 18716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 188b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("received data:"); 18916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 194916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 195916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 196916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 198b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending data:"); 19923d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 200916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 201916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 202b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 203916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 205916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 211916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 212b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending response %04X", mResponse.getResponseCode()); 213916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21423d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 21516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 216b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 217916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 218916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 219916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 223916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 22421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("skipping response\n"); 22516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2276b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // commit any open edits 2297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 2337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.clear(); 2367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2376b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2386b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 23916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 24016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 241873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 242a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectAdded %d\n", handle); 243a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 244873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 245873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 246873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 247a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectRemoved %d\n", handle); 248a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 249a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 250a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 251a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 252a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreAdded %08X\n", id); 253a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 254a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 255a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 257a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreRemoved %08X\n", id); 258a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 259a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 260a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 261a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 26273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 263a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 26473ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 265a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 26673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 26759d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("mEvent.write returned %d\n", ret); 26873ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 269873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 270873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 2717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, 2727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t size, MtpObjectFormat format, int fd) { 2737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = new ObjectEdit; 2747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->handle = handle; 2757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->path = path; 2767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->size = size; 2777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->format = format; 2787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->fd = fd; 2797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.add(edit); 2807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { 2837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit->handle == handle) return edit; 2877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return NULL; 2897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::removeEditObject(MtpObjectHandle handle) { 2927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit->handle == handle) { 2967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.removeAt(i); 2987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return; 2997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 3007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 3017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("ObjectEdit not found in removeEditObject"); 3027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::commitEdit(ObjectEdit* edit) { 3057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mDatabase->endSendObject((const char *)edit->path, edit->handle, edit->format, true); 3067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 309916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 310a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 311a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 31216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 31316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 31416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 31616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 319b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("expected SendObject after SendObjectInfo"); 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 32416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 34116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 34316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 345343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 346343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 347343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 348438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 349438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 350438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 351438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 352438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 353438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 35516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 35616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3598277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3608277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3618277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3678277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 369b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 370b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 371b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 37216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 37316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 37416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 37516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 37616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 37716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 378d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 3797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT_64: 3807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doGetPartialObject(operation); 381d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 38216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 38316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 39116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 39221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 39321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 394e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 395e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 396e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 3977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_SEND_PARTIAL_OBJECT: 3987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doSendPartialObject(); 3997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_TRUNCATE_OBJECT: 4017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doTruncateObject(); 4027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_BEGIN_EDIT_OBJECT: 4047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doBeginEditObject(); 4057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_END_EDIT_OBJECT: 4077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doEndEditObject(); 4087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 40916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 410a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation)); 41116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 41416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 415916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 416916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 41716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 418916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 41916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 42216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 423c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 42416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 425782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 426782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 427782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 428782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(6); // MTP Vendor Extension ID 43216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood string.set("microsoft.com: 1.0; android.com: 1.0;"); 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 43516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 438873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 439873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 440782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 441782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 442782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 4438d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 4448d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 4458d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 447c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 448c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 449c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 45016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 45116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 45216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 453c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 454c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 455c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 45616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 45716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 458782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 459782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 460782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 461782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 46516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 46616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 46716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 46816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 46916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 47016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 47116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 4726b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 4736b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 4746b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 47516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 47616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 47716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 48116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 48216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 4836b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 48416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 48516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 48616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 48716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 48816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 48916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 49316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 49516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 49816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 50016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 50116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 50316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 50416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 50516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 5262e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 527782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 528bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 53516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 536e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 53816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 0x00000000 for all objects? 539a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 540a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 541a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 5421865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == 0xFFFFFFFF) 5431865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 54816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 54916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 55016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 551343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 552343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 553343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 554343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 555343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 556343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 557343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood // 0x00000000 for all objects? 558a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 559a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 560343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (parent == 0xFFFFFFFF) 561343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood parent = 0; 562343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 563343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 564343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 565343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 566343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 567343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 568343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 569343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 570343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 571343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 572343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 573438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 574438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 575438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 576a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 577a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 578a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 5798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 581438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 5828277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 5838277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 5848277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 5858277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 586438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 587438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 588438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 589438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 590438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 591438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 592438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 593438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 594a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 595a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 596438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 597a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 598438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 599438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 600438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 601438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 602438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 603438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 60416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 605a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 606a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 60716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 60816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 60959d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropValue %d %s\n", handle, 6108277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 61116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6128277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 6138277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6148277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6158277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 616a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 617a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 6188277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6198277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 62059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetObjectPropValue %d %s\n", handle, 6218277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 6228277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6238277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 6248277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6258277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6268277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 6278277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 62859d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropValue %s\n", 6298277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6308277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6318277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 6328277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6338277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6348277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 6358277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 63659d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetDevicePropValue %s\n", 6378277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6388277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6398277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 6408277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6418277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6428277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 6438277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 64459d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("ResetDevicePropValue %s\n", 6458277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6468277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6478277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 64816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 64916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 650b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 651a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 652a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 653b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 654b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 65540ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 65640ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 65740ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 658b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 659f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 66059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 661b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 662b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 663b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 664b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 665b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 666b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 66716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 668a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 669a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 67016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectInfo info(handle); 6727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpResponseCode result = mDatabase->getObjectInfo(handle, info); 6737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result == MTP_RESPONSE_OK) { 6747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood char date[20]; 6757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mStorageID); 6777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mFormat); 6787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mProtectionStatus); 6797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // if object is being edited the database size may be out of date 6817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t size = info.mCompressedSize; 6827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 6837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit) 6847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood size = (edit->size > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->size); 6857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(size); 6867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mThumbFormat); 6887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbCompressedSize); 6897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixWidth); 6907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixHeight); 6917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixWidth); 6927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixHeight); 6937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixDepth); 6947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mParent); 6957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mAssociationType); 6967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mAssociationDesc); 6977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mSequenceNumber); 6987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(info.mName); 6997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // date created 7007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood formatDateTime(info.mDateModified, date, sizeof(date)); 7017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(date); // date modified 7027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // keywords 7037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 7047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 70516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 70616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 70716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 708a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 709a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 71016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 711c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 71216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 713fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 714fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 7159c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7169c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 71716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7189c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 71916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 720c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 721c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 722c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 723c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 72416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 72516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 72616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 72716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // send data header 72816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 72916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 73023d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE); 73116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 73316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 734c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 735916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 736916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 737916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 738916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 739916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 740916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 74116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 74216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 74316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7447d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { 745a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 746a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 747d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 7487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset; 7497d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length; 7507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = mRequest.getParameter(2); 7517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { 7527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // android extension with 64 bit offset 7537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 7547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 7557d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(4); 7567d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 7577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // standard GetPartialObject 7587d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(3); 7597d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 760d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 761d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 762fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 763fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 764d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 765d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 766d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (offset + length > fileLength) 767d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 768d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 769d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 770d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 771d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 772d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 773d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 774d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 775d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 776d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 777d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 778d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 779d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // send data header 780d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 781d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 782d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE); 783d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 784d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // then transfer the file 785d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 786d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 787d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 788d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 789d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 790d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 791d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 792d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 793d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 794d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 795d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 79616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 79716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 79816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 79916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 80016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 80116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 80216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 80316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 80416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 8051865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 80616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 8071865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 8081865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 809fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 810fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 811fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 8129c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 8139c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 814fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 815fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 81616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 81716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 81816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 81916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 82016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 82116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 82216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 82316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 82416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 82516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 82616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 82716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 82816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 82916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 83016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 83116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 83216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 83316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 83416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 83516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 83616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 83716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 83816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 83916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("name: %s format: %04X\n", (const char *)name, format); 841fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 84216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 84316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 84416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 84616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 84716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 84816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84920c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 85020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 85120c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 85220c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 853a849440ca96e93f700d62c6e41d48905b4d405b6Mike LockwoodLOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 8544714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 8554714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 856fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 85716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 858fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 85916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 86016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 86116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 8628e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 86316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 86416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 86516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 8668e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 867aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 868aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 869aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 87016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 87116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 87216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 87316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 8744714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 87516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 87616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 87716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 8788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 87916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 88016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 88216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 88316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 885a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 886a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 8874714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 8884714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 8894714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood int ret; 8904714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 89116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 892b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("Expected SendObjectInfo before SendObject"); 8934714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 8944714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 89516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 89616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 89716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read the header 8984714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood ret = mData.readDataHeader(mFD); 89916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 90016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // reset so we don't attempt to send this back 90216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 90316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 905c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); 906c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 9074714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 9084714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 909c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 9108e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 9118e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 9124714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 9138e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 9148e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 9158e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 91616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 91716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = mSendObjectFileSize; 91816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91959d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("receiving %s\n", (const char *)mSendObjectFilePath); 92016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // transfer the file 92116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 922c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 9238e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 924b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 92516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 926916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 927916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 928916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 9294714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 930916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 9314714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 932916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 9334714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 9344714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 9354714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 936aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 9374714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 9384714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 9394714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 94016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 94116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 942d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 943d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 944d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathLength = strlen(path); 945d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 946d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path too long: %s\n", path); 947d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 948d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 949d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 950d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 951d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 952d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 953d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 954d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 955d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 956d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 957d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("opendir %s failed: %s", path, strerror(errno)); 958d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 959d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 960d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 961d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 962d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 963d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 964d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 965d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 966d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 967d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 968d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 969d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 970d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 971d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 972d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path %s/%s too long\n", path, name); 973d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 974d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 975d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 976d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 977d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 978d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 979d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 980d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 981d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 982d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 983d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 984d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 9857ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 986d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 987d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 988d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 989d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 990d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 991d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 992d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 993d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 994d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 995d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 996d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 997d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 998d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 999d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1000d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1001d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 100216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 1003a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 1004a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 100516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 1006d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 100716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 100816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 100916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 101016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 101116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 1012fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 10139c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 10149c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood LOGV("deleting %s", (const char *)filePath); 1015d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deletePath((const char *)filePath); 10169c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return mDatabase->deleteFile(handle); 10179c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } else { 10189c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 10199c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 102016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 102116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 102216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 102321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 102416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 102559d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 10268277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 10278277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 102821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 102921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 10308277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 10318277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 10328277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 10338277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 103416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 10358277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 10368277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 103759d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 10388277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 10398277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 10408277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 104121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 10428277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 104321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 104416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10457850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 10467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doSendPartialObject() { 10477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!hasStorage()) 10487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 10497d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 10507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 10517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 10527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 10537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length = mRequest.getParameter(4); 10547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10557d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 10567d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 10577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doSendPartialObject"); 10587d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 10597d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10607d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10617d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // can't start writing past the end of the file 10627d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (offset > edit->size) { 10637d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGD("writing past end of object, offset: %lld, edit->size: %lld", offset, edit->size); 10647d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 10657d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10677d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // read the header 10687d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int ret = mData.readDataHeader(mFD); 10697d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // FIXME - check for errors here. 10707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // reset so we don't attempt to send this back 10727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.reset(); 10737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood const char* filePath = (const char *)edit->path; 10757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGV("receiving partial %s %lld %ld\n", filePath, offset, length); 10767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mtp_file_range mfr; 10777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mfr.fd = edit->fd; 10787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mfr.offset = offset; 10797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mfr.length = length; 10807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // transfer the file 10827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 10837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 10847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ret < 0) { 10857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, 0); 10867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (errno == ECANCELED) 10877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 10887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood else 10897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 10907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, length); 10927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t end = offset + length; 10937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (end > edit->size) { 10947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->size = end; 10957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 10967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 10977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 10987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doTruncateObject() { 11007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 11037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doTruncateObject"); 11047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset |= (offset2 << 32); 11107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ftruncate(edit->fd, offset) != 0) { 11117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 11137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood edit->size = offset; 11147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11167d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doBeginEditObject() { 11197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (getEditObject(handle)) { 11217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object already open for edit in doBeginEditObject"); 11227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpString path; 11267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int64_t fileLength; 11277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectFormat format; 11287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); 11297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result != MTP_RESPONSE_OK) 11307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 11317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int fd = open((const char *)path, O_RDWR | O_EXCL); 11337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (fd < 0) { 11347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); 11357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood addEditObject(handle, path, fileLength, format, fd); 11397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11407d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doEndEditObject() { 11437d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11447d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11457d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 11467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood LOGE("object not open for edit in doEndEditObject"); 11477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11497d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 11517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood removeEditObject(handle); 11527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11557850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 1156