MtpServer.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/* 216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License. 616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at 716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and 1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License. 1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */ 1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h> 1816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdlib.h> 1916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/types.h> 2016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/ioctl.h> 2116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/stat.h> 2216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <fcntl.h> 2316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <errno.h> 24d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <sys/stat.h> 25d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <dirent.h> 2616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 27c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 28c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 29a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood#define LOG_TAG "MtpServer" 30a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 327f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood#include "MtpObjectInfo.h" 3421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 398065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 4016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 417850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 427850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 5364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MTP_OPERATION_GET_THUMB, 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 63e3e76c456baee122de6715ae280130abaddc906cMike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 70d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT, 7116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 738277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_DESC, 74677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 75677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 76b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_LIST, 77b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_LIST, 78b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, 79b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SEND_OBJECT_PROP_LIST, 80438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 81438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // Android extension for direct file IO 847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT_64, 857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_SEND_PARTIAL_OBJECT, 867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_TRUNCATE_OBJECT, 877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_BEGIN_EDIT_OBJECT, 887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_END_EDIT_OBJECT, 8916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 9016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 92873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 93873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 94a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_ADDED, 95a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_REMOVED, 96873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 97873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 983d1d7767afc7c488197ec40a22739159c5110721Mike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp, 998e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1011865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1023d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mPtp(ptp), 1038e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1048e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1058e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 10616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 10716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1094714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 11116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 117a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 118a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 126a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 127a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 128a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 129a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 130a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 131a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 132a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 133a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 137fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 138fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 140fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 147a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 148a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 149a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 150a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 151a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 152a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MtpServer::run fd: %d\n", fd); 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 1613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("request read returned %d, errno: %d", ret, errno); 162916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 163916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 164916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 165916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1713856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 175438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 17916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 18229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("data read returned %d, errno: %d", ret, errno); 183916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 184916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 186916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 18816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 1893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("received data:"); 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 195916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 196916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 1993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending data:"); 20023d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 201916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 202916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 20329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 205916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 212916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 2133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending response %04X", mResponse.getResponseCode()); 214916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21523d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 21616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 21729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 218916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 219916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 221916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 224916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 2253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipping response\n"); 22616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2286b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // commit any open edits 2307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 2347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.clear(); 2377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2386b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2396b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 240dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood close(fd); 241dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood mFD = -1; 24216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 24316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 244873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 2453856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectAdded %d\n", handle); 246a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 247873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 248873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 249873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 2503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectRemoved %d\n", handle); 251a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 252a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 253a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 254a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 2553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreAdded %08X\n", id); 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 257a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 258a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 259a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 2603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreRemoved %08X\n", id); 261a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 262a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 263a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 264a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 26573ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 266a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 26773ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 268a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 26973ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 2703856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mEvent.write returned %d\n", ret); 27173ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 272873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 273873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 2747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, 2757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t size, MtpObjectFormat format, int fd) { 276c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd); 2777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.add(edit); 2787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { 2817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 284c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) return edit; 2857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return NULL; 2877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::removeEditObject(MtpObjectHandle handle) { 2907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 293c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) { 2947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.removeAt(i); 2967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return; 2977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 29929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("ObjectEdit not found in removeEditObject"); 3007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::commitEdit(ObjectEdit* edit) { 303c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true); 3047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 307916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 308a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 309a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 31016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 31116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 31216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 31416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 31616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 31729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("expected SendObject after SendObjectInfo"); 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 32416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 34116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 343343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 344343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 345343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 346438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 347438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 348438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 349438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 350438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 351438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3598277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3608277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3618277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 367b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 368b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 369b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 37016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 37116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 37216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 37316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 37416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 37516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 37664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood case MTP_OPERATION_GET_THUMB: 37764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood response = doGetThumb(); 37864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood break; 379d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 3807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT_64: 3817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doGetPartialObject(operation); 382d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 38316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 39116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 39216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 39321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 39421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 395e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 396e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 397e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 3987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_SEND_PARTIAL_OBJECT: 3997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doSendPartialObject(); 4007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_TRUNCATE_OBJECT: 4027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doTruncateObject(); 4037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_BEGIN_EDIT_OBJECT: 4057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doBeginEditObject(); 4067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_END_EDIT_OBJECT: 4087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doEndEditObject(); 4097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 41016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 41129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation)); 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 41416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 41516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 416916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 417916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 41816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 419916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 42316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 424c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 426782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 427782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 428782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 429782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4323d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4333d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(0); 4343d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4353d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP Vendor Extension ID 4363d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(6); 4373d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4393d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4403d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // no extensions 4413d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set(""); 4423d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4433d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP extensions 4443d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set("microsoft.com: 1.0; android.com: 1.0;"); 4453d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 44816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 44916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 450873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 451873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 452782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 453782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 454782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 4558d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 4568d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 4578d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 45816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 459c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 460c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 461c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 465c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 466c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 467c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 46816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 46916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 470782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 471782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 472782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 473782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 47416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 47516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 47616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 47716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 48116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 48216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 48316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 4846b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 4856b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 4866b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 48716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 48816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 48916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 49316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 4956b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 49816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 50016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 50116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 50216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 50416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 50516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 52716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 52816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 53516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 53616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 5382e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 539782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 540bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 548e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 54916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 550dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 551a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 552a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 553a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 55416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 55616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 55716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 55816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 55916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 56016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 561343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 562343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 563343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 564343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 565343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 566343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 567dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 568a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 569a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 570343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 571343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 572343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 573343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 574343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 575343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 576343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 577343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 578343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 579343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 580343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 581438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 582438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 583438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 584a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 585a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 586a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 5878277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5888277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 589438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 5908277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 5918277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 5928277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 5938277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 594438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 595438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 596438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 597438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 598438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 599438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 600438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 601438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 602a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 603a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 604438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 605a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 606438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 607438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 608438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 609438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 610438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 611438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 61216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 613a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 614a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 61516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 61616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6173856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropValue %d %s\n", handle, 6188277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 61916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6208277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 6218277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6228277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6238277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 624a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 625a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 6268277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6278277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetObjectPropValue %d %s\n", handle, 6298277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 6308277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6318277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 6328277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6338277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6348277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 6358277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropValue %s\n", 6378277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6388277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6398277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 6408277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6418277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6428277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 6438277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetDevicePropValue %s\n", 6458277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6468277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6478277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 6488277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6498277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6508277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 6518277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ResetDevicePropValue %s\n", 6538277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 65616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 65716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 658b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 659a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 660a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 661b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 662b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 66340ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 66440ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 66540ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 666b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 667f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 6683856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 669b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 670b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 671b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 672b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 673b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 674b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 67516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 676a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 677a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 67816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectInfo info(handle); 6807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpResponseCode result = mDatabase->getObjectInfo(handle, info); 6817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result == MTP_RESPONSE_OK) { 6827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood char date[20]; 6837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mStorageID); 6857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mFormat); 6867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mProtectionStatus); 6877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // if object is being edited the database size may be out of date 6897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t size = info.mCompressedSize; 6907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 6917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit) 692c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize); 6937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(size); 6947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 6957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mThumbFormat); 6967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbCompressedSize); 6977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixWidth); 6987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixHeight); 6997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixWidth); 7007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixHeight); 7017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixDepth); 7027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mParent); 7037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mAssociationType); 7047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mAssociationDesc); 7057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mSequenceNumber); 7067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(info.mName); 7077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // date created 7087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood formatDateTime(info.mDateModified, date, sizeof(date)); 7097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(date); // date modified 7107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // keywords 7117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 7127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 71316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 71416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 71516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 716a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 717a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 71816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 719c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 72016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 721fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 722fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 7239c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7249c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 72516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7269c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 72716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 728c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 729c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 730c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 731c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 73216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 73316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 734ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 735ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 73616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 738ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 7393856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 740c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 741916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 742916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 743916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 744916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 745916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 746916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 74716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 74816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 74916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 75064000788211f4c7e78c80a4a155390d1316e1176Mike LockwoodMtpResponseCode MtpServer::doGetThumb() { 75164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 75264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood size_t thumbSize; 75364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood void* thumb = mDatabase->getThumbnail(handle, thumbSize); 75464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood if (thumb) { 75564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood // send data 75664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 75764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 75864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.writeData(mFD, thumb, thumbSize); 75964000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood free(thumb); 76064000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_OK; 76164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } else { 76264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 76364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } 76464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood} 76564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood 7667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { 767a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 768a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 769d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 7707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset; 7717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length; 7727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = mRequest.getParameter(2); 7737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { 7747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // android extension with 64 bit offset 7757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 7767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 7777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(4); 7787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 7797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // standard GetPartialObject 7807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(3); 7817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 782d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 783d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 784fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 785fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 786d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 787d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 788d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (offset + length > fileLength) 789d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 790d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 791d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 792d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 793d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 794d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 795d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 796d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 797d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 798d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 799ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 800ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 801d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 802d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 803ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // transfer the file 804ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 8053856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 806d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 807d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 808d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 809d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 810d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 811d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 812d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 813d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 814d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 815d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 81616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 81716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 81816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 81916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 82016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 82116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 82216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 82316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 82416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 8251865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 82616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 8271865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 8281865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 829fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 830fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 831fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 8329c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 8339c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 834fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 835fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 83616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 83716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 83816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 83916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 84016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 84116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 84216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 84316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 84416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 84516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 84616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 84716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 84816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 84916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 85016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 85116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 85216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 85316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 85416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 85516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 85616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 85716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 85816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 85916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 8603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("name: %s format: %04X\n", (const char *)name, format); 861fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 86216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 86316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 86416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 86516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 86616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 86716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 86816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 86920c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 87020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 87120c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 8729b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood uint64_t maxFileSize = storage->getMaxFileSize(); 8739b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // check storage max file size 8749b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (maxFileSize != 0) { 8759b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size 8769b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // is >= 0xFFFFFFFF 8779b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF) 8789b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood return MTP_RESPONSE_OBJECT_TOO_LARGE; 8799b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood } 88020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 881b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 8824714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 8834714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 884fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 88516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 886fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 88716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 88816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 88916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 8908e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 89116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 89216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 89316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 8948e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 895aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 896aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 897aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 89816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 89916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 90016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 90116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 9024714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 90316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 90416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 9068277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 90716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 90816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 91016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 91116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 913a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 914a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9154714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 9164714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 917ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret, initialData; 9184714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 91916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 92029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Expected SendObjectInfo before SendObject"); 9214714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 9224714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 92316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 92416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 925ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 926ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = mData.read(mFD); 927ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) { 928ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 929ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood goto done; 930ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 931ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood initialData = ret - MTP_CONTAINER_HEADER_SIZE; 93216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 93316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 934c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); 935c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 9364714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 9374714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 938c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 9398e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 9408e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 9414714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 9428e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 9438e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 9448e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 945ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (initialData > 0) 946ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = write(mfr.fd, mData.getData(), initialData); 94716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 948ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (mSendObjectFileSize - initialData > 0) { 949ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.offset = initialData; 9500cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood if (mSendObjectFileSize == 0xFFFFFFFF) { 9510cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood // tell driver to read until it receives a short packet 9520cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood mfr.length = 0xFFFFFFFF; 9530cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood } else { 9540cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood mfr.length = mSendObjectFileSize - initialData; 9550cc79c66329b9ffa7d7bdfafa5d245a11fd3660dMike Lockwood } 9568e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 9573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("receiving %s\n", (const char *)mSendObjectFilePath); 958ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // transfer the file 959ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 9603856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_RECEIVE_FILE returned %d\n", ret); 961ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 962ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood close(mfr.fd); 96316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 964916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 965916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 966916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 9674714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 968916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 9694714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 970916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 9714714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 9724714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 973ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send the data back 974ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 975ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 9764714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 977aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 9784714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 9794714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 9804714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 98116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 98216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 983d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 984d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 985d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathLength = strlen(path); 986d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 98729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path too long: %s\n", path); 988d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 989d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 990d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 991d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 992d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 993d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 994d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 995d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 996d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 997d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 99829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("opendir %s failed: %s", path, strerror(errno)); 999d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 1000d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1001d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1002d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 1003d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 1004d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 1005d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1006d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 1007d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 1008d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1009d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1010d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1011d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 1012d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 101329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path %s/%s too long\n", path, name); 1014d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1015d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1016d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 1017d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1018d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 1019d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 1020d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 1021d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 1022d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1023d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 1024d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1025d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 10267ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 1027d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1028d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1029d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 1030d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 1031d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 1032d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 1033d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 1034d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 1035d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1036d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 1037d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1038d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 103929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 1040d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1041d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1042d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 104316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 1044a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 1045a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 104616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 1047d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 104816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 104916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 105016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 105116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 105216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 1053fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 10549c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 10553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("deleting %s", (const char *)filePath); 1056a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood result = mDatabase->deleteFile(handle); 1057a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood // Don't delete the actual files unless the database deletion is allowed 1058a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood if (result == MTP_RESPONSE_OK) { 1059a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood deletePath((const char *)filePath); 1060a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood } 10619c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 1062a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood 1063a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood return result; 106416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 106516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 106616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 106721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 106816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 10693856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 10708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 10718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 107221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 107321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 10748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 10758277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 10768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 10778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 107816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 10798277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 10808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 10813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 10828277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 10838277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 10848277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 108521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 10868277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 108721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 108816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10897850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 10907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doSendPartialObject() { 10917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!hasStorage()) 10927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 10937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 10947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 10957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 10967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 10977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length = mRequest.getParameter(4); 10987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 10997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 110129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doSendPartialObject"); 11027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // can't start writing past the end of the file 1106c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (offset > edit->mSize) { 1107b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize); 11087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1111ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood const char* filePath = (const char *)edit->mPath; 11123856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("receiving partial %s %lld %lld\n", filePath, offset, length); 11137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1114ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 1115ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = mData.read(mFD); 1116ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) 1117ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 1118ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int initialData = ret - MTP_CONTAINER_HEADER_SIZE; 11197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1120ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (initialData > 0) { 1121ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = write(edit->mFD, mData.getData(), initialData); 1122ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood offset += initialData; 1123ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood length -= initialData; 1124ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 11257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1126ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (length > 0) { 1127ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mtp_file_range mfr; 1128ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.fd = edit->mFD; 1129ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.offset = offset; 1130ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.length = length; 1131ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 1132ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // transfer the file 1133ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 11343856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_RECEIVE_FILE returned %d", ret); 1135ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 11367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ret < 0) { 11377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, 0); 11387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (errno == ECANCELED) 11397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 11407d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood else 11417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 1143ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 1144ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send this back 1145ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 11467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, length); 11477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t end = offset + length; 1148c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (end > edit->mSize) { 1149c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = end; 11507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doTruncateObject() { 11557d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11567d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 115829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doTruncateObject"); 11597d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11607d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11617d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11627d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11637d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11647d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset |= (offset2 << 32); 1165c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (ftruncate(edit->mFD, offset) != 0) { 11667d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11677d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 1168c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = offset; 11697d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doBeginEditObject() { 11747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (getEditObject(handle)) { 117629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object already open for edit in doBeginEditObject"); 11777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpString path; 11817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int64_t fileLength; 11827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectFormat format; 11837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); 11847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result != MTP_RESPONSE_OK) 11857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 11867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int fd = open((const char *)path, O_RDWR | O_EXCL); 11887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (fd < 0) { 118929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); 11907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11917d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood addEditObject(handle, path, fileLength, format, fd); 11947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 11957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 11967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doEndEditObject() { 11987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 12007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 120129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doEndEditObject"); 12027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 12067d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood removeEditObject(handle); 12077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12107850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 1211