116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/* 216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License. 616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at 716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and 1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License. 1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */ 1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h> 1816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdlib.h> 1916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/types.h> 2016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/ioctl.h> 2116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/stat.h> 2216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <fcntl.h> 23db43b34c3428e480f8c4c66e7e88f4001f37f91eMark Salyzyn#include <inttypes.h> 2416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <errno.h> 25d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <sys/stat.h> 26d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <dirent.h> 2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 28c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 29c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 30a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood#define LOG_TAG "MtpServer" 31a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood 3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 337f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood#include "MtpObjectInfo.h" 3521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 408065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 4116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 427850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 437850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 5464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MTP_OPERATION_GET_THUMB, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 64e3e76c456baee122de6715ae280130abaddc906cMike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 678277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 7016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 71d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT, 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_DESC, 75677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 76677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 77b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_LIST, 78b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_LIST, 79b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, 80b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SEND_OBJECT_PROP_LIST, 81438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 82438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // Android extension for direct file IO 857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT_64, 867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_SEND_PARTIAL_OBJECT, 877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_TRUNCATE_OBJECT, 887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_BEGIN_EDIT_OBJECT, 897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MTP_OPERATION_END_EDIT_OBJECT, 9016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 9116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 92873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 93873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 94873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 95a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_ADDED, 96a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_REMOVED, 970fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood MTP_EVENT_DEVICE_PROP_CHANGED, 98873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 99873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 1003d1d7767afc7c488197ec40a22739159c5110721Mike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, bool ptp, 1018e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 10216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1031865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1043d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mPtp(ptp), 1058e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1068e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1078e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 10916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1114714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 11716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 126a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 127a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 128a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 1293ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mStorages.size(); i++) { 130a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 131a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 132a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 133a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 134a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 135a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 139fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 140fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 1413ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn for (size_t i = 0; i < mStorages.size(); i++) { 142fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 149a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 150a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 151a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 152a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 153a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 154a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MtpServer::run fd: %d\n", fd); 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 1633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("request read returned %d, errno: %d", ret, errno); 164916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 165916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 166916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 167916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1733856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 177438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 18216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 18429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("data read returned %d, errno: %d", ret, errno); 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 186916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 187916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 188916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 1913856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("received data:"); 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 199916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 200916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 2013856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending data:"); 20223d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 203916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 20529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 211916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 212916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 214916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 2153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sending response %04X", mResponse.getResponseCode()); 216916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21723d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 21816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 21929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("request write returned %d, errno: %d", ret, errno); 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 221916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 222916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 223916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 226916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 2273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipping response\n"); 22816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2306b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // commit any open edits 2327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 2357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 2367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 2377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.clear(); 2397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2406b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2416b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 242dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood close(fd); 243dec7388c3edf09eaaccaaf57f6301e716319a34dMike Lockwood mFD = -1; 24416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 24516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 246873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 2473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectAdded %d\n", handle); 248a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 249873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 250873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 251873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 2523856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendObjectRemoved %d\n", handle); 253a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 254a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 255a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 2573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreAdded %08X\n", id); 258a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 259a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 260a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 261a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 2623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sendStoreRemoved %08X\n", id); 263a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 264a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 265a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 2660fa848d780cf990a2860637f40432d28594c85a3Mike Lockwoodvoid MtpServer::sendDevicePropertyChanged(MtpDeviceProperty property) { 2670fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood ALOGV("sendDevicePropertyChanged %d\n", property); 2680fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood sendEvent(MTP_EVENT_DEVICE_PROP_CHANGED, property); 2690fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood} 2700fa848d780cf990a2860637f40432d28594c85a3Mike Lockwood 271a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 27273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 273a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 27473ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 275a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 27673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 2773856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mEvent.write returned %d\n", ret); 27873ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 279873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 280873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 2817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path, 2827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t size, MtpObjectFormat format, int fd) { 283c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd); 2847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.add(edit); 2857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) { 2887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 291c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) return edit; 2927d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 2937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return NULL; 2947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 2957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 2967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::removeEditObject(MtpObjectHandle handle) { 2977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int count = mObjectEditList.size(); 2987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood for (int i = 0; i < count; i++) { 2997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = mObjectEditList[i]; 300c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (edit->mHandle == handle) { 3017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood delete edit; 3027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mObjectEditList.removeAt(i); 3037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return; 3047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 3057d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 30629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("ObjectEdit not found in removeEditObject"); 3077d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3087d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3097d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwoodvoid MtpServer::commitEdit(ObjectEdit* edit) { 310c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true); 3117d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 3127d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 3137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 314916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 315a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 316a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 31716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 32429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("expected SendObject after SendObjectInfo"); 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 328dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen int containertype = mRequest.getContainerType(); 329dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (containertype != MTP_CONTAINER_TYPE_COMMAND) { 330dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("wrong container type %d", containertype); 331dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen return false; 332dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 333dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 334dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("got command %s (%x)", MtpDebug::getOperationCodeName(operation), operation); 335dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 34116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 34516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 34716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 34816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 35016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 35116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 35516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 35616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 35716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 358343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 359343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 360343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 361438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 362438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 363438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 364438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 365438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 366438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 36716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3728277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3738277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3758277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3818277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 382b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 383b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 384b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 39164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood case MTP_OPERATION_GET_THUMB: 39264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood response = doGetThumb(); 39364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood break; 394d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 3957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT_64: 3967d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doGetPartialObject(operation); 397d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 39816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 39916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 40016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 40216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 40316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 40516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 40616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 40716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 40821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 40921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 410e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 411e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 412e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 4137d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_SEND_PARTIAL_OBJECT: 4147d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doSendPartialObject(); 4157d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4167d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_TRUNCATE_OBJECT: 4177d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doTruncateObject(); 4187d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_BEGIN_EDIT_OBJECT: 4207d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doBeginEditObject(); 4217d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 4227d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood case MTP_OPERATION_END_EDIT_OBJECT: 4237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood response = doEndEditObject(); 4247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood break; 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 426dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("got unsupported command %s (%x)", 427dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen MtpDebug::getOperationCodeName(operation), operation); 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 432916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 433916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 435916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 43916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 440c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 44116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 442782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 443782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 444782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 445782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4483d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4493d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(0); 4503d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4513d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP Vendor Extension ID 4523d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood mData.putUInt32(6); 4533d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 45416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 4553d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood if (mPtp) { 4563d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // no extensions 4573d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set(""); 4583d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } else { 4593d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood // MTP extensions 4603d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood string.set("microsoft.com: 1.0; android.com: 1.0;"); 4613d1d7767afc7c488197ec40a22739159c5110721Mike Lockwood } 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 46516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 466873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 467873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 468782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 469782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 470782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 4718d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 4728d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 4738d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 47416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 475c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 476c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 477c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 481c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 482c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 483c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 48416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 48516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 486782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 487782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 488782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 489782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 49516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 498ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 499ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 500ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood 50116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 50216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 5036b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 5046b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 5056b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 5146b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 52816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 535ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 536ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 537ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood 53816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 53916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 54816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 54916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 55016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 55116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 55216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 55416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 55516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 55716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 55816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 559ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 560ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 56116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 5622e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 563782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 564bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 56516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 56616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 56716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 56816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 56916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 57016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 571ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 3) 572ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 57316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 574e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 57516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 576dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 577a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 578a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 579a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 58016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 58116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 58216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 58316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 58416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 58516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 58616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 587343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 588343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 589343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 590ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 3) 591ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 592343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 593343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 594343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 595dc3185e3e27b05e18c4ac34432a25a0c279ff351Mike Lockwood // 0x00000000 for all objects 596a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 597a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 598343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 599343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 600343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 601343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 602343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 603343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 604343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 605343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 606343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 607343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 608343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 609438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 610438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 611438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 612a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 613a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 614ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 615ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 616a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6178277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6188277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 619438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 6208277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 6218277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 6228277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 6238277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 624438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 625438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 626438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 627438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 628438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 629438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 630438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 631438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 632a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 633a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 634ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 635ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 636438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 637a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 638438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 639ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!references) 640ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 641438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 642438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 643438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 644438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 645438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 64616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 647a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 648a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 649ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 2) 650ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 65116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 65216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6533856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropValue %d %s\n", handle, 6548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 65516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 6578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6598277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 660a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 661a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 662ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 2) 663ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 6648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 6658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 6663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetObjectPropValue %d %s\n", handle, 6678277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 6688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6698277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 6708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6728277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 673ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 674ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 6758277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropValue %s\n", 6778277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 6808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6818277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6828277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 683ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 684ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 6858277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6863856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("SetDevicePropValue %s\n", 6878277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6888277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6898277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 6908277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 6918277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6928277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 693ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 694ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 6958277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 6963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("ResetDevicePropValue %s\n", 6978277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 6988277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 6998277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 70016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 70116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 702b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 703a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 704a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 705ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 5) 706ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 707b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 708b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 70940ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 71040ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 71140ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 712b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 713f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 7143856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 715b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 716b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 717b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 718b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 719b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 720b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 72116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 722a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 723a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 724ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 725ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 72616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 7277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectInfo info(handle); 7287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpResponseCode result = mDatabase->getObjectInfo(handle, info); 7297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result == MTP_RESPONSE_OK) { 7307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood char date[20]; 7317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mStorageID); 7337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mFormat); 7347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mProtectionStatus); 7357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // if object is being edited the database size may be out of date 7377d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t size = info.mCompressedSize; 7387d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 7397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (edit) 740c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize); 7417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(size); 7427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 7437d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mThumbFormat); 7447d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbCompressedSize); 7457d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixWidth); 7467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mThumbPixHeight); 7477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixWidth); 7487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixHeight); 7497d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mImagePixDepth); 7507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mParent); 7517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt16(info.mAssociationType); 7527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mAssociationDesc); 7537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putUInt32(info.mSequenceNumber); 7547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(info.mName); 755ec24fa46443634cd29627182c5812ccf43682692Mike Lockwood formatDateTime(info.mDateCreated, date, sizeof(date)); 756ec24fa46443634cd29627182c5812ccf43682692Mike Lockwood mData.putString(date); // date created 7577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood formatDateTime(info.mDateModified, date, sizeof(date)); 7587d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putString(date); // date modified 7597d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mData.putEmptyString(); // keywords 7607d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 7617d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 76216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 76316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 76416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 765a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 766a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 767ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 768ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 76916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 770c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 77116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 772fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 773fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 7749c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7759c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 77616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7779c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 77816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 779c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 780c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 781c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 782c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 78316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 78416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 785ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 786ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 78716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 78816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 789ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 7903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 791c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 792916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 793916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 794916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 795916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 796916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 797916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 79816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 79916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 80016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 80164000788211f4c7e78c80a4a155390d1316e1176Mike LockwoodMtpResponseCode MtpServer::doGetThumb() { 802ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 803ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 80464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 80564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood size_t thumbSize; 80664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood void* thumb = mDatabase->getThumbnail(handle, thumbSize); 80764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood if (thumb) { 80864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood // send data 80964000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 81064000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 81164000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood mData.writeData(mFD, thumb, thumbSize); 81264000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood free(thumb); 81364000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_OK; 81464000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } else { 81564000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 81664000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood } 81764000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood} 81864000788211f4c7e78c80a4a155390d1316e1176Mike Lockwood 8197d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) { 820a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 821a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 822d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 8237d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset; 8247d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length; 8257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = mRequest.getParameter(2); 8267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) { 827e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood // MTP_OPERATION_GET_PARTIAL_OBJECT_64 takes 4 arguments 828e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood if (mRequest.getParameterCount() < 4) 829e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 830e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood 8317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // android extension with 64 bit offset 8327d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 8337d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 8347d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(4); 8357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 836e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood // MTP_OPERATION_GET_PARTIAL_OBJECT takes 3 arguments 837e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood if (mRequest.getParameterCount() < 3) 838e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 839e48cf5b8f823c30af93577c1e380d752ac69b871Mike Lockwood 8407d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // standard GetPartialObject 8417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood length = mRequest.getParameter(3); 8427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 843d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 844d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 845fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 846fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 847d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 848d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 849d239cb6e6898bdf2300e9038111727a9056c58eeMark Salyzyn if (offset + length > (uint64_t)fileLength) 850d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 851d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 852d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 853d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 854d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 855d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 856d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 857d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 858d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 859d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 860ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.command = mRequest.getOperationCode(); 861ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mfr.transaction_id = mRequest.getTransactionID(); 862d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 863d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 864ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // transfer the file 865ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr); 8663856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret); 867d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 868d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 869d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 870d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 871d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 872d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 873d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 874d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 875d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 876d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 87716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 87816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 879ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint16_t temp16; 880ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint32_t temp32; 881ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood 882ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 2) 883ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 88416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 88516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 88616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 88716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 88816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 88916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 89016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 8911865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 89216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 8931865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 8941865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 895fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 896fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 897fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 8989c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 8999c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 900fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 901fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 90216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 90316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 905ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // storage ID 906ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; 907ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood MtpObjectFormat format = temp16; 908ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // protection status 909ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; 910ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood mSendObjectFileSize = temp32; 911ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb format 912ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb compressed size 913ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix width 914ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix height 915ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix width 916ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix height 917ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image bit depth 918ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // parent 919ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; 920ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint16_t associationType = temp16; 921ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; 922ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood uint32_t associationDesc = temp32; // association desc 923ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // sequence number 92416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 925ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER; // file name 926ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getString(created)) return MTP_RESPONSE_INVALID_PARAMETER; // date created 927ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER; // date modified 92816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 92916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 9303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("name: %s format: %04X\n", (const char *)name, format); 931fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 93216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 93316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 93416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 93516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 93616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 93716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 93816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 93920c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 94020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 94120c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 9429b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood uint64_t maxFileSize = storage->getMaxFileSize(); 9439b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // check storage max file size 9449b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (maxFileSize != 0) { 9459b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size 9469b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood // is >= 0xFFFFFFFF 9479b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF) 9489b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood return MTP_RESPONSE_OBJECT_TOO_LARGE; 9499b88b72ee2c3fd01fb46e77b7e6d80f3bd52e958Mike Lockwood } 95020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 951b8a805261bf0282e992d3608035e47d05a898710Steve Block ALOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 9524714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 9534714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 954fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 95516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 956fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 95716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 95816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 95916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 9608e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 96116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 96216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 96316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9648e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 965aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 966aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 967aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 96816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 96916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 97016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 97116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 9724714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 97316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 97416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 97516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 9768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 97716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 97816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 97916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 98016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 98116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 98216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 983a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 984a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 9854714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 9864714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 987ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret, initialData; 9884714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 98916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 99029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Expected SendObjectInfo before SendObject"); 9914714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 9924714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 99316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 99416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 995ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 996ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = mData.read(mFD); 997ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) { 998ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 999ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood goto done; 1000ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 1001ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood initialData = ret - MTP_CONTAINER_HEADER_SIZE; 100216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 100316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 1004af8e8aa1ada2948972555592570ec9ad90cbf372Nick Kralevich mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); 1005c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 10064714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 10074714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 1008c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 10098e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 10108e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 10114714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 10128e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 10138e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 10148e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 1015dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (initialData > 0) { 1016ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood ret = write(mfr.fd, mData.getData(), initialData); 1017dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 101816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1019dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (ret < 0) { 1020dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("failed to write initial data"); 1021dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen result = MTP_RESPONSE_GENERAL_ERROR; 1022dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 1023dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (mSendObjectFileSize - initialData > 0) { 1024dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.offset = initialData; 1025dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (mSendObjectFileSize == 0xFFFFFFFF) { 1026dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // tell driver to read until it receives a short packet 1027dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = 0xFFFFFFFF; 1028dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 1029dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = mSendObjectFileSize - initialData; 1030dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 10318e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 1032dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("receiving %s\n", (const char *)mSendObjectFilePath); 1033dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // transfer the file 1034dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 1035dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("MTP_RECEIVE_FILE returned %d\n", ret); 1036dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 1037ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 1038ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood close(mfr.fd); 103916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1040916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 1041916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 1042916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 10434714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 1044916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 10454714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 1046916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 10474714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 10484714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 1049ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send the data back 1050ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 1051ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 10524714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 1053aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 10544714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 10554714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 10564714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 105716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 105816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1059d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 1060d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 1061d239cb6e6898bdf2300e9038111727a9056c58eeMark Salyzyn size_t pathLength = strlen(path); 1062d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 106329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path too long: %s\n", path); 1064d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1065d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 1066d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 1067d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 1068d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1069d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 1070d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 1071d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1072d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 1073d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 107429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("opendir %s failed: %s", path, strerror(errno)); 1075d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 1076d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1077d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1078d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 1079d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 1080d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 1081d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1082d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 1083d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 1084d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1085d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1086d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1087d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 1088d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 108929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("path %s/%s too long\n", path, name); 1090d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 1091d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1092d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 1093d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1094d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 1095d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 1096d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 1097d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 1098d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1099d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 1100d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1101d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 11027ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 1103d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1104d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 1105d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 1106d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 1107d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 1108d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 1109d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 1110d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 1111d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 1112d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 1113d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1114d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 111529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 1116d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 1117d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 1118d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 111916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 1120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 1121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 1122ea9f215a13f1a5e6455be91624a81a024641a26dMarco Nelissen if (mRequest.getParameterCount() < 1) 1123ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 112416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 1125ea9f215a13f1a5e6455be91624a81a024641a26dMarco Nelissen MtpObjectFormat format; 112616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 112716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 112816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 112916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 113016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 1131fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 11329c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 11333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("deleting %s", (const char *)filePath); 1134a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood result = mDatabase->deleteFile(handle); 1135a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood // Don't delete the actual files unless the database deletion is allowed 1136a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood if (result == MTP_RESPONSE_OK) { 1137a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood deletePath((const char *)filePath); 1138a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood } 11399c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 1140a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood 1141a9a46c1f53129be8fe1f3f0a6ea868d7b4c8f8f7Mike Lockwood return result; 114216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 114316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 114416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 1145ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 2) 1146ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 114721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 114816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 11493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 11508277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 11518277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 115221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 115321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 11548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 11558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 11568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 11578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 115816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11598277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 1160ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 1161ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 11628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 11633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 11648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 11658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 11668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 116721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 11688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 116921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 117016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 11717850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 11727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doSendPartialObject() { 11737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!hasStorage()) 11747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 1175ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 4) 1176ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 11777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 11787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 11797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 11807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset = offset | (offset2 << 32); 11817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint32_t length = mRequest.getParameter(4); 11827d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 11847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 118529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doSendPartialObject"); 11867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 11897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood // can't start writing past the end of the file 1190c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (offset > edit->mSize) { 1191d239cb6e6898bdf2300e9038111727a9056c58eeMark Salyzyn ALOGD("writing past end of object, offset: %" PRIu64 ", edit->mSize: %" PRIu64, 1192d239cb6e6898bdf2300e9038111727a9056c58eeMark Salyzyn offset, edit->mSize); 11937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 11947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 11957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1196ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood const char* filePath = (const char *)edit->mPath; 1197d239cb6e6898bdf2300e9038111727a9056c58eeMark Salyzyn ALOGV("receiving partial %s %" PRIu64 " %" PRIu32, filePath, offset, length); 11987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1199ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // read the header, and possibly some data 1200ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int ret = mData.read(mFD); 1201ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (ret < MTP_CONTAINER_HEADER_SIZE) 1202ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 1203ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood int initialData = ret - MTP_CONTAINER_HEADER_SIZE; 12047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1205ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood if (initialData > 0) { 12060a694951c00f2135c8968fd2205f71899997a8adMike Lockwoood ret = pwrite(edit->mFD, mData.getData(), initialData, offset); 1207ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood offset += initialData; 1208ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood length -= initialData; 1209ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 12107d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 1211dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (ret < 0) { 1212dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGE("failed to write initial data"); 1213dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } else { 1214dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen if (length > 0) { 1215dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mtp_file_range mfr; 1216dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.fd = edit->mFD; 1217dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.offset = offset; 1218dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen mfr.length = length; 1219dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen 1220dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen // transfer the file 1221dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 1222dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen ALOGV("MTP_RECEIVE_FILE returned %d", ret); 1223dcd89ecad321e2e052322fe2b1907d50d762b311Marco Nelissen } 1224ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood } 12257d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (ret < 0) { 12267d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, 0); 12277d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (errno == ECANCELED) 12287d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 12297d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood else 12307d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12317d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 1232ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood 1233ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood // reset so we don't attempt to send this back 1234ef441d965504dbf31c5db690e5b34fcdcecd92ffMike Lockwood mData.reset(); 12357d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood mResponse.setParameter(1, length); 12367d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t end = offset + length; 1237c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (end > edit->mSize) { 1238c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = end; 12397d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12407d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12417d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12427d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12437d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doTruncateObject() { 1244ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 3) 1245ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 12467d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 12477d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 12487d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 124929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doTruncateObject"); 12507d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12517d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12527d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12537d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset = mRequest.getParameter(2); 12547d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood uint64_t offset2 = mRequest.getParameter(3); 12557d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood offset |= (offset2 << 32); 1256c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood if (ftruncate(edit->mFD, offset) != 0) { 12577d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12587d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } else { 1259c3f16e5620c090aeb75c0836572a8b913a4ef864Mike Lockwood edit->mSize = offset; 12607d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12617d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12627d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12637d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12647d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doBeginEditObject() { 1265ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 1266ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 12677d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 12687d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (getEditObject(handle)) { 126929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object already open for edit in doBeginEditObject"); 12707d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12717d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12727d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12737d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpString path; 12747d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int64_t fileLength; 12757d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectFormat format; 12767d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, path, fileLength, format); 12777d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (result != MTP_RESPONSE_OK) 12787d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return result; 12797d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12807d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood int fd = open((const char *)path, O_RDWR | O_EXCL); 12817d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (fd < 0) { 128229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno); 12837d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12847d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12857d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12867d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood addEditObject(handle, path, fileLength, format, fd); 12877d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 12887d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 12897d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 12907d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike LockwoodMtpResponseCode MtpServer::doEndEditObject() { 1291ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood if (mRequest.getParameterCount() < 1) 1292ab063847e6e893740749029a04cce1f6b7345ed5Mike Lockwood return MTP_RESPONSE_INVALID_PARAMETER; 12937d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 12947d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood ObjectEdit* edit = getEditObject(handle); 12957d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood if (!edit) { 129629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("object not open for edit in doEndEditObject"); 12977d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 12987d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood } 12997d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 13007d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood commitEdit(edit); 13017d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood removeEditObject(handle); 13027d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood return MTP_RESPONSE_OK; 13037d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood} 13047d77dcfadd7fb637ed2c3aef5bb3990dd0a67dc0Mike Lockwood 13057850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 1306