MtpServer.cpp revision a849440ca96e93f700d62c6e41d48905b4d405b6
116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/* 216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License. 616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at 716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * 1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and 1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License. 1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */ 1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h> 1816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdlib.h> 1916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/types.h> 2016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/ioctl.h> 2116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <sys/stat.h> 2216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <fcntl.h> 2316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <errno.h> 24d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <sys/stat.h> 25d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood#include <dirent.h> 2616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 27c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 28c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 29a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood#define LOG_TAG "MtpServer" 30a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 327f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 3321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 388065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 407850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 417850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 4216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_THUMB, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 62e3e76c456baee122de6715ae280130abaddc906cMike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 69d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MTP_OPERATION_GET_PARTIAL_OBJECT, 7016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 7116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 728277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_DESC, 73677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 74677f5700c5ea35256079ef14e06b7382e438d860Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 75b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_LIST, 76b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_LIST, 77b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC, 78b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood// MTP_OPERATION_SEND_OBJECT_PROP_LIST, 79438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 80438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 8116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 84873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 85873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 86873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 87a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_ADDED, 88a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MTP_EVENT_STORE_REMOVED, 89873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 90873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 911865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, 928e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 9316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 941865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 958e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 968e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 978e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 9816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 9916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1014714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 10216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 10316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 10416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 10616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 10716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 109a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::addStorage(MtpStorage* storage) { 110a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 111a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 112a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.push(storage); 113a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreAdded(storage->getStorageID()); 114a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 115a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 116a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::removeStorage(MtpStorage* storage) { 117a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 118a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 119a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 120a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (mStorages[i] == storage) { 121a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mStorages.removeAt(i); 122a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendStoreRemoved(storage->getStorageID()); 123a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood break; 124a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 125a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood } 12616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 12716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 12816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 129fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (id == 0) 130fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return mStorages[0]; 13116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 132fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpStorage* storage = mStorages[i]; 13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 139a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodbool MtpServer::hasStorage(MtpStorageID id) { 140a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (id == 0 || id == 0xFFFFFFFF) 141a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return mStorages.size() > 0; 142a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return (getStorage(id) != NULL); 143a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 144a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("MtpServer::run fd: %d\n", fd); 14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 15116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 15359d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("request read returned %d, errno: %d", ret, errno); 154916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 155916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 156916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 157916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 163b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 16416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 16516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 167438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 1688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES 1698277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE 1708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE); 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 174b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("data read returned %d, errno: %d", ret, errno); 175916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 176916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 177916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 178916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 17916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 181b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("received data:"); 18216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 18316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 18416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 18516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 18616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 187916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 188916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 189916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 190916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 191b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending data:"); 19223d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.dump(); 193916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 194916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 195b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 196916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 199916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 200916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 201916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 202916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 20316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 204916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 205b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending response %04X", mResponse.getResponseCode()); 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 20723d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mResponse.dump(); 20816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 209b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 211916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 212916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 213916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 21516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 216916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 21721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("skipping response\n"); 21816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 21916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 2206b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 2216b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood if (mSessionOpen) 2226b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 22316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 22416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 225873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 226a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectAdded %d\n", handle); 227a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_ADDED, handle); 228873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 229873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 230873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 231a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendObjectRemoved %d\n", handle); 232a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_OBJECT_REMOVED, handle); 233a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 234a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 235a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreAdded(MtpStorageID id) { 236a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreAdded %08X\n", id); 237a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_ADDED, id); 238a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 239a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 240a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendStoreRemoved(MtpStorageID id) { 241a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood LOGV("sendStoreRemoved %08X\n", id); 242a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood sendEvent(MTP_EVENT_STORE_REMOVED, id); 243a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood} 244a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 245a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwoodvoid MtpServer::sendEvent(MtpEventCode code, uint32_t param1) { 24673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 247a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setEventCode(code); 24873ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 249a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood mEvent.setParameter(1, param1); 25073ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 25159d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("mEvent.write returned %d\n", ret); 25273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 253873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 254873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 255916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 256a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood Mutex::Autolock autoLock(mMutex); 257a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 25816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 25916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 26016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 26116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 26216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 26316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 26416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 265b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("expected SendObject after SendObjectInfo"); 26616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 26716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 26816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 26916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 27016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 27116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 27216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 27316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 27416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 27516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 27616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 27716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 27816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 27916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 28016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 28116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 28216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 28316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 28416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 28516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 28616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 28716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 28816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 28916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 29016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 291343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 292343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 293343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 294438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 295438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 296438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 297438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 298438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 299438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 30016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 30116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 30216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 3038277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_OBJECT_PROP_VALUE: 3048277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetObjectPropValue(); 3058277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3068277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_VALUE: 3078277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doGetDevicePropValue(); 3088277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3098277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_SET_DEVICE_PROP_VALUE: 3108277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doSetDevicePropValue(); 3118277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 3128277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood case MTP_OPERATION_RESET_DEVICE_PROP_VALUE: 3138277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood response = doResetDevicePropValue(); 3148277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood break; 315b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_LIST: 316b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood response = doGetObjectPropList(); 317b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood break; 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 324d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood case MTP_OPERATION_GET_PARTIAL_OBJECT: 325d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood response = doGetPartialObject(); 326d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood break; 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 33721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 33821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 339e3e76c456baee122de6715ae280130abaddc906cMike Lockwood case MTP_OPERATION_GET_DEVICE_PROP_DESC: 340e3e76c456baee122de6715ae280130abaddc906cMike Lockwood response = doGetDevicePropDesc(); 341e3e76c456baee122de6715ae280130abaddc906cMike Lockwood break; 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 343a881b44cc7e18bdfa03251bc65b7d0903a1b1efcMike Lockwood LOGE("got unsupported command %s", MtpDebug::getOperationCodeName(operation)); 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 34516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 34716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 348916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 349916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 35016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 351916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 35516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 356c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 35716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 358782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats(); 359782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats(); 360782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties(); 361782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 36216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 36316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 36416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(6); // MTP Vendor Extension ID 36516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 36616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("microsoft.com: 1.0;"); 36716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 37016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 371873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 372873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 373782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(deviceProperties); // Device Properties Supported 374782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(captureFormats); // Capture Formats 375782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(playbackFormats); // Playback Formats 3768d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood 3778d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood property_get("ro.product.manufacturer", prop_value, "unknown manufacturer"); 3788d08c5aeee05425357b6603a22fa73fd6e095a47Mike Lockwood string.set(prop_value); 37916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 380c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 381c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 382c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 38316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 386c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 387c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 388c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 391782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete playbackFormats; 392782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete captureFormats; 393782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood delete deviceProperties; 394782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood 39516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 39616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 39716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 39816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 39916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 40016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 40116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 40216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 40316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 40416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 4056b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 4066b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionStarted(); 4076b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood 40816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 40916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 41016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 41416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 41516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 4166b3a9d15c8a2282c03f1df7d72a55b6800d4ececMike Lockwood mDatabase->sessionEnded(); 41716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 41816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 41916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 42216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 42316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 42616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 42716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 43216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 43316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 43516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 43916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 44016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 44116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 44216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 44316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 44416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 44516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 44816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 44916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 45016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 45116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 45216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 45316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 45416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 45516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 45616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 45716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 45816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 4592e09e289b7e136481e9215bb61ed47cee5d9919bMike Lockwood MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format); 460782aef17c9921a3bf401a0432878df5031f2328bMike Lockwood mData.putAUInt16(properties); 461bf9b2052d207f8f2a23470f1c4dfe464f430f387Mike Lockwood delete properties; 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 46516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 46616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 46716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 46816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 469e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 47016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 47116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 0x00000000 for all objects? 472a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 473a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 474a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 4751865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == 0xFFFFFFFF) 4761865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 47716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 48116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 48216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 48316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 484343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 485343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 486343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 487343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 488343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 489343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 490343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood // 0x00000000 for all objects? 491a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage(storageID)) 492a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 493343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (parent == 0xFFFFFFFF) 494343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood parent = 0; 495343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 496343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 497343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 498343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 499343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 500343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 501343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 502343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 503343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 504343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 505343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 506438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 507438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 508438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 509a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 510a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 511a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 5128277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5138277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood // FIXME - check for invalid object handle 514438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 5158277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (handles) { 5168277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mData.putAUInt32(handles); 5178277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete handles; 5188277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood } else { 519438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 520438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 521438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 522438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 523438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 524438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 525438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 526438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 527a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 528a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 529438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 530a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood 531438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 532438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 533438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 534438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 535438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 536438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 538a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 539a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 54259d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropValue %d %s\n", handle, 5438277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 5458277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getObjectPropertyValue(handle, property, mData); 5468277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 5478277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5488277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetObjectPropValue() { 549a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 550a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 5518277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 5528277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 55359d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetObjectPropValue %d %s\n", handle, 5548277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getObjectPropCodeName(property)); 5558277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5568277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setObjectPropertyValue(handle, property, mData); 5578277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 5588277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5598277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropValue() { 5608277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 56159d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropValue %s\n", 5628277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 5638277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5648277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->getDevicePropertyValue(property, mData); 5658277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 5668277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5678277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doSetDevicePropValue() { 5688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 56959d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("SetDevicePropValue %s\n", 5708277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 5718277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5728277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->setDevicePropertyValue(property, mData); 5738277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 5748277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5758277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doResetDevicePropValue() { 5768277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty property = mRequest.getParameter(1); 57759d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("ResetDevicePropValue %s\n", 5788277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getDevicePropCodeName(property)); 5798277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood 5808277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return mDatabase->resetDeviceProperty(property); 58116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 58216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 583b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropList() { 584a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 585a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 586b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 587b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 58840ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood // use uint32_t so we can support 0xFFFFFFFF 58940ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t format = mRequest.getParameter(2); 59040ce1f262cc4edbc8b7c470830325466263acaecMike Lockwood uint32_t property = mRequest.getParameter(3); 591b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood int groupCode = mRequest.getParameter(4); 592f05ff073495b0bb3e49859aee5b54d3e25088985Mike Lockwood int depth = mRequest.getParameter(5); 59359d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", 594b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood handle, MtpDebug::getFormatCodeName(format), 595b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood MtpDebug::getObjectPropCodeName(property), groupCode, depth); 596b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 597b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); 598b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood} 599b6da06e9dfb916da4b88e09e8a83e22ddae445b5Mike Lockwood 60016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 601a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 602a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 60316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 60416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return mDatabase->getObjectInfo(handle, mData); 60516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 60616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 60716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 608a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 609a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 61016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 611c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 61216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 613fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 614fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 6159c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 6169c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 61716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6189c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 61916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 620c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 621c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 622c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 623c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 62416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 62516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 62616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 62716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // send data header 62816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 62916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 63023d2071ab44d7b5e3b16e8a81e11884faf01092fMike Lockwood mData.writeDataHeader(mFD, fileLength + MTP_CONTAINER_HEADER_SIZE); 63116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 63216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 63316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 634c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 635916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 636916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 637916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 638916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 639916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 640916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 64116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 64216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 64316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 644d81ce3cf2e6479915658a0829eced062e3655320Mike LockwoodMtpResponseCode MtpServer::doGetPartialObject() { 645a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 646a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 647d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 648d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood uint32_t offset = mRequest.getParameter(2); 649d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood uint32_t length = mRequest.getParameter(3); 650d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood MtpString pathBuf; 651d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int64_t fileLength; 652fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 653fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); 654d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (result != MTP_RESPONSE_OK) 655d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return result; 656d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (offset + length > fileLength) 657d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood length = fileLength - offset; 658d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 659d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood const char* filePath = (const char *)pathBuf; 660d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mtp_file_range mfr; 661d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.fd = open(filePath, O_RDONLY); 662d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (mfr.fd < 0) { 663d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 664d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 665d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.offset = offset; 666d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mfr.length = length; 667d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mResponse.setParameter(1, length); 668d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 669d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // send data header 670d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 671d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 672d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood mData.writeDataHeader(mFD, length + MTP_CONTAINER_HEADER_SIZE); 673d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 674d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood // then transfer the file 675d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 676d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood close(mfr.fd); 677d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (ret < 0) { 678d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood if (errno == ECANCELED) 679d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 680d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood else 681d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 682d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood } 683d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood return MTP_RESPONSE_OK; 684d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood} 685d81ce3cf2e6479915658a0829eced062e3655320Mike Lockwood 68616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 68716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 68816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 68916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 69016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 69116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 69216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 69316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 69416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 6951865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 69616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 6971865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 6981865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 699fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int64_t length; 700fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood MtpObjectFormat format; 701fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, length, format); 7029c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 7039c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 704fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood if (format != MTP_FORMAT_ASSOCIATION) 705fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood return MTP_RESPONSE_INVALID_PARENT_OBJECT; 70616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 70716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 70816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 70916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 71016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 71116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 71216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 71316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 71416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 71516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 71616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 71716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 71816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 71916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 72016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 72116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 72216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 72316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 72416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 72516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 72616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 72716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 72816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 72916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73059d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("name: %s format: %04X\n", (const char *)name, format); 731fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 73216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 73316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 73416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 73616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 73716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 73816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 73920c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood // check space first 74020c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood if (mSendObjectFileSize > storage->getFreeSpace()) 74120c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood return MTP_RESPONSE_STORAGE_FULL; 74220c3be0e0394e1340c036685eb1edb8f6ef5a2acMike Lockwood 743a849440ca96e93f700d62c6e41d48905b4d405b6Mike LockwoodLOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID); 7444714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 7454714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 746fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 74716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 748fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 74916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 75016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 75116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 7528e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 75316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 75416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 75516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 7568e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 757aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood 758aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood // SendObject does not get sent for directories, so call endSendObject here instead 759aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK); 76016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 76116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 76216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 76316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 7644714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 76516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 76616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 76716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 7688277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood mResponse.setParameter(2, parent); 76916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 77016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 77116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 77216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 77316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 77416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 775a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 776a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 7774714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 7784714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 7794714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood int ret; 7804714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 78116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 782b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("Expected SendObjectInfo before SendObject"); 7834714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 7844714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 78516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 78616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 78716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read the header 7884714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood ret = mData.readDataHeader(mFD); 78916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 79016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 79116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // reset so we don't attempt to send this back 79216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 79316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 79416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 795c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); 796c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 7974714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 7984714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 799c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 8008e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 8018e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 8024714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 8038e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 8048e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 8058e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 80616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 80716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = mSendObjectFileSize; 80816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 80959d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("receiving %s\n", (const char *)mSendObjectFilePath); 81016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // transfer the file 81116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 812c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 8138e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 814b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 81516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 816916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 817916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 818916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 8194714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 820916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 8214714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 822916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 8234714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 8244714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 8254714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 826aa95240d9096f97aa2e2022fae8764a4386c8951Mike Lockwood result == MTP_RESPONSE_OK); 8274714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 8284714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 8294714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 83016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 83116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 832d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deleteRecursive(const char* path) { 833d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char pathbuf[PATH_MAX]; 834d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathLength = strlen(path); 835d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathLength >= sizeof(pathbuf) - 1) { 836d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path too long: %s\n", path); 837d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 838d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(pathbuf, path); 839d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (pathbuf[pathLength - 1] != '/') { 840d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood pathbuf[pathLength++] = '/'; 841d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 842d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood char* fileSpot = pathbuf + pathLength; 843d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int pathRemaining = sizeof(pathbuf) - pathLength - 1; 844d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 845d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood DIR* dir = opendir(path); 846d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (!dir) { 847d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("opendir %s failed: %s", path, strerror(errno)); 848d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood return; 849d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 850d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 851d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct dirent* entry; 852d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood while ((entry = readdir(dir))) { 853d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood const char* name = entry->d_name; 854d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 855d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood // ignore "." and ".." 856d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) { 857d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 858d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 859d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 860d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int nameLength = strlen(name); 861d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (nameLength > pathRemaining) { 862d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("path %s/%s too long\n", path, name); 863d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood continue; 864d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 865d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood strcpy(fileSpot, name); 866d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 867d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood int type = entry->d_type; 868d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (entry->d_type == DT_DIR) { 869d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(pathbuf); 870d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(pathbuf); 871d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 872d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(pathbuf); 873d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 874d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 8757ce05cf6009a2fbbceb3d2c0ff639473d0b7d6a9Mike Lockwood closedir(dir); 876d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 877d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 878d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwoodstatic void deletePath(const char* path) { 879d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood struct stat statbuf; 880d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (stat(path, &statbuf) == 0) { 881d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood if (S_ISDIR(statbuf.st_mode)) { 882d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deleteRecursive(path); 883d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood rmdir(path); 884d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 885d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood unlink(path); 886d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 887d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } else { 888d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood LOGE("deletePath stat failed for %s: %s", path, strerror(errno)); 889d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood } 890d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood} 891d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood 89216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 893a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood if (!hasStorage()) 894a849440ca96e93f700d62c6e41d48905b4d405b6Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 89516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 896d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 89716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 89816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 89916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 90016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 90116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 902fd34626771a63d3a835863e1b4bf71dcb26e28d8Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); 9039c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 9049c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood LOGV("deleting %s", (const char *)filePath); 905d32114950770a6e9361e0869a41e5a03a7acab42Mike Lockwood deletePath((const char *)filePath); 9069c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return mDatabase->deleteFile(handle); 9079c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } else { 9089c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 9099c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 91016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 91116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 91216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 91321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 91416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 91559d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode), 9168277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDebug::getFormatCodeName(format)); 9178277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format); 91821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 91921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 9208277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood property->write(mData); 9218277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 9228277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_OK; 9238277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood} 92416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 9258277cec96ffa55082962591bca1c55abbeec8c26Mike LockwoodMtpResponseCode MtpServer::doGetDevicePropDesc() { 9268277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpDeviceProperty propCode = mRequest.getParameter(1); 92759d6ae5e339547fea8a350c1d855b52d5ac4f62cMike Lockwood LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode)); 9288277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode); 9298277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood if (!property) 9308277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 93121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 9328277cec96ffa55082962591bca1c55abbeec8c26Mike Lockwood delete property; 93321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 93416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 9357850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 9367850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 937