MtpServer.cpp revision 438344fba74ddd6b931ac733fa48643f27b63de3
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> 2416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 25c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood#include <cutils/properties.h> 26c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 287f53a190463274096155704276f3002c1620a364Mike Lockwood#include "MtpDatabase.h" 2921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood#include "MtpProperty.h" 3016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 3316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 348065e2056073808716db32136d7acfd50eeab924Mike Lockwood#include <linux/usb/f_mtp.h> 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 367850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 377850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 4016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 4116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 4216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_THUMB, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 58343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood// MTP_OPERATION_GET_DEVICE_PROP_DESC, 59343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood// MTP_OPERATION_GET_DEVICE_PROP_VALUE, 60343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood// MTP_OPERATION_SET_DEVICE_PROP_VALUE, 61343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood// MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 6416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 6516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_PARTIAL_OBJECT, 6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_OBJECT_PROP_DESC, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 70343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROP_VALUE, 71438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_GET_OBJECT_REFERENCES, 72438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_OPERATION_SET_OBJECT_REFERENCES, 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 7416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 7516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 76873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodstatic const MtpEventCode kSupportedEventCodes[] = { 77873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_ADDED, 78873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood MTP_EVENT_OBJECT_REMOVED, 79873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood}; 80873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 8116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpObjectProperty kSupportedObjectProperties[] = { 8216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_STORAGE_ID, 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_FORMAT, 8416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_SIZE, 8516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_FILE_NAME, 8616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_PARENT_OBJECT, 8716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 8816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 8916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpObjectFormat kSupportedPlaybackFormats[] = { 90fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_UNDEFINED, 9116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_FORMAT_ASSOCIATION, 92fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_TEXT, 93fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_HTML, 9416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_FORMAT_MP3, 95fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood //MTP_FORMAT_AVI, 96fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MPEG, 97fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_ASF, 98fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_EXIF_JPEG, 99fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_TIFF_EP, 100fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_BMP, 101fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_GIF, 102fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_JFIF, 103fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_PNG, 104fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_TIFF, 105fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_WMA, 106fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_OGG, 107fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_AAC, 108fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_FLAC, 109fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_WMV, 110fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MP4_CONTAINER, 111fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MP2, 112fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_3GP_CONTAINER, 113fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_ABSTRACT_AUDIO_ALBUM, 114438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_FORMAT_ABSTRACT_AV_PLAYLIST, 115438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_FORMAT_WPL_PLAYLIST, 116438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_FORMAT_M3U_PLAYLIST, 117fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_MPL_PLAYLIST, 118438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MTP_FORMAT_PLS_PLAYLIST, 11916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 12016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 1211865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike LockwoodMtpServer::MtpServer(int fd, MtpDatabase* database, 1228e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int fileGroup, int filePerm, int directoryPerm) 12316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 1241865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mDatabase(database), 1258e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFileGroup(fileGroup), 1268e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mFilePermission(filePerm), 1278e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood mDirectoryPermission(directoryPerm), 12816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 12916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 13016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 1314714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat(0), 13216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 13421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood initObjectProperties(); 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::addStorage(const char* filePath) { 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int index = mStorages.size() + 1; 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood index |= index << 16; // set high and low part to our index 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = new MtpStorage(index, filePath, mDatabase); 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood addStorage(storage); 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = mStorages[i]; 15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 15116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15921ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("MtpServer::run fd: %d\n", fd); 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 16316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 164b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request read returned %d, errno: %d", ret, errno); 165916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 166916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 167916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 168916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 174b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("operation: %s", MtpDebug::getOperationCodeName(operation)); 17516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 17616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 17716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 178438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO 179438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood || operation == MTP_OPERATION_SET_OBJECT_REFERENCES); 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 18216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 183b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("data read returned %d, errno: %d", ret, errno); 184916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 185916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 186916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 187916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 18816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 18916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 190b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("received data:"); 19116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 196916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (handleRequest()) { 197916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (!dataIn && mData.hasData()) { 198916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setOperationCode(operation); 199916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.setTransactionID(transaction); 200b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending data:"); 201916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mData.dump(); 202916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mData.write(fd); 203916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 204b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 205916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 206916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 207916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 208916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 209916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood break; 210916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 211916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 21216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 213916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood mResponse.setTransactionID(transaction); 214b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("sending response %04X", mResponse.getResponseCode()); 215916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood ret = mResponse.write(fd); 21616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 217b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("request write returned %d, errno: %d", ret, errno); 218916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) { 219916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood // return to top of loop and wait for next command 220916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood continue; 221916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 22216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 224916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } else { 22521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood LOGV("skipping response\n"); 22616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 22816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 22916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 23021ef7d0e70c5ad599bc2602cb484f8cd647055caMike LockwoodMtpProperty* MtpServer::getObjectProperty(MtpPropertyCode propCode) { 23121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood for (int i = 0; i < mObjectProperties.size(); i++) { 23221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpProperty* property = mObjectProperties[i]; 23321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (property->getPropertyCode() == propCode) 23421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return property; 23521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood } 23621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return NULL; 23721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood} 23821ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood 23921ef7d0e70c5ad599bc2602cb484f8cd647055caMike LockwoodMtpProperty* MtpServer::getDeviceProperty(MtpPropertyCode propCode) { 24021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood for (int i = 0; i < mDeviceProperties.size(); i++) { 24121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpProperty* property = mDeviceProperties[i]; 24221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (property->getPropertyCode() == propCode) 24321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return property; 24421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood } 24521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return NULL; 24621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood} 24721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood 248873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectAdded(MtpObjectHandle handle) { 24973ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 25073ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood LOGD("sendObjectAdded %d\n", handle); 25173ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED); 25273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 25373ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setParameter(1, handle); 25473ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 25573ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood LOGD("mEvent.write returned %d\n", ret); 25673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 257873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 258873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 259873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwoodvoid MtpServer::sendObjectRemoved(MtpObjectHandle handle) { 26073ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood if (mSessionOpen) { 26173ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood LOGD("sendObjectRemoved %d\n", handle); 26273ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED); 26373ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setTransactionID(mRequest.getTransactionID()); 26473ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood mEvent.setParameter(1, handle); 26573ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood int ret = mEvent.write(mFD); 26673ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood LOGD("mEvent.write returned %d\n", ret); 26773ecd23cc2ebadb8e1fae1cc21ac559524c6b2bbMike Lockwood } 268873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood} 269873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood 27021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwoodvoid MtpServer::initObjectProperties() { 27121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood mObjectProperties.push(new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT16)); 27221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16)); 27321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64)); 27421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR)); 27521ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood mObjectProperties.push(new MtpProperty(MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32)); 27621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood} 27721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood 278916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwoodbool MtpServer::handleRequest() { 27916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 28016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 28116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 28216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 28316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 28416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 28516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 286b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("expected SendObject after SendObjectInfo"); 28716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 28816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 28916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 29016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 29116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 29216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 29316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 29416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 29516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 29616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 29716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 29816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 29916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 30016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 30116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 30216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 30316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 30416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 30516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 30616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 30716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 30816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 30916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 31016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 31116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 312343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood case MTP_OPERATION_GET_NUM_OBJECTS: 313343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood response = doGetNumObjects(); 314343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood break; 315438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_GET_OBJECT_REFERENCES: 316438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doGetObjectReferences(); 317438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 318438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood case MTP_OPERATION_SET_OBJECT_REFERENCES: 319438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood response = doSetObjectReferences(); 320438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood break; 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 34021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood response = doGetObjectPropDesc(); 34121ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood break; 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 34316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 34516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 34616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 347916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (response == MTP_RESPONSE_TRANSACTION_CANCELLED) 348916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return false; 34916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 350916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return true; 35116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 355c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood char prop_value[PROPERTY_VALUE_MAX]; 35616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 35716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 35816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 35916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(6); // MTP Vendor Extension ID 36016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 36116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("microsoft.com: 1.0;"); 36216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 36316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 36416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 36516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 366873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood mData.putAUInt16(kSupportedEventCodes, 367873871f3e75831bcda6c3f75bb4d53355ca5c53aMike Lockwood sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyArray(); // Device Properties Supported 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyArray(); // Capture Formats 37016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedPlaybackFormats, 37116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedPlaybackFormats) / sizeof(uint16_t)); // Playback Formats 37216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME 37316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("Google, Inc."); 37416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 375c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 376c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.product.model", prop_value, "MTP Device"); 377c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 37816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 37916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 38016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 381c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood 382c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood property_get("ro.serialno", prop_value, "????????"); 383c42aa12f73edf79bc9cb0dbf6b74a7f1af11c683Mike Lockwood string.set(prop_value); 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 39116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 39216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 39316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 39416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 39516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 39616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 39716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 39816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 39916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 40016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 40116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 40216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 40316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 40416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 40516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 40616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 40716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 40816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 40916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 41016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 41416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 41516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 41716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 41816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 42316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 42416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 42616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 42716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 43216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 43316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 43516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 43916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 44016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 44116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 44216864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 44316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 44416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 44516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedObjectProperties, 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedObjectProperties) / sizeof(uint16_t)); 44816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 44916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 45016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 45116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 45216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 45316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 45416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 455e13401bf532c7e4bf9ab82c7e9b13642838a927dMike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 45616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 45716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 0x00000000 for all objects? 4581865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == 0xFFFFFFFF) 4591865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 46016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 46116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 46216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 46316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 46516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 46616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 467343af4ef512869695456a91519e73ed3c3d82101Mike LockwoodMtpResponseCode MtpServer::doGetNumObjects() { 468343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (!mSessionOpen) 469343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 470343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 471343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats 472343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 473343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood // 0x00000000 for all objects? 474343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (parent == 0xFFFFFFFF) 475343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood parent = 0; 476343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 477343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood int count = mDatabase->getNumObjects(storageID, format, parent); 478343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood if (count >= 0) { 479343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, count); 480343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_OK; 481343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } else { 482343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood mResponse.setParameter(1, 0); 483343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 484343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood } 485343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood} 486343af4ef512869695456a91519e73ed3c3d82101Mike Lockwood 487438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doGetObjectReferences() { 488438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 489438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 490438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 491438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); 492438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!handles) { 493438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putEmptyArray(); 494438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 495438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood } 496438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood mData.putAUInt32(handles); 497438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete handles; 498438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_OK; 499438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 500438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 501438344fba74ddd6b931ac733fa48643f27b63de3Mike LockwoodMtpResponseCode MtpServer::doSetObjectReferences() { 502438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood if (!mSessionOpen) 503438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 504438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpStorageID handle = mRequest.getParameter(1); 505438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpObjectHandleList* references = mData.getAUInt32(); 506438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 507438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood delete references; 508438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood return result; 509438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood} 510438344fba74ddd6b931ac733fa48643f27b63de3Mike Lockwood 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return mDatabase->getObjectProperty(handle, property, mData); 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return mDatabase->getObjectInfo(handle, mData); 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 525c6588763ddc20541688e426a24b1b070527c051fMike Lockwood MtpString pathBuf; 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 5279c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength); 5289c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 5299c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 5319c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood const char* filePath = (const char *)pathBuf; 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 533c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(filePath, O_RDONLY); 534c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 535c6588763ddc20541688e426a24b1b070527c051fMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 536c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 53816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 53916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // send data header 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.writeDataHeader(mFD, fileLength); 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 547c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 548916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 549916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 550916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_TRANSACTION_CANCELLED; 551916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 552916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 553916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 55416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 55516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 55616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 55716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 55816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 55916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 56016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 56116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 56216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 56316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 56416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 56516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 5661865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood if (parent == MTP_PARENT_ROOT) { 56716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 5681865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood parent = 0; 5691865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood } else { 57016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t dummy; 5719c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood int result = mDatabase->getObjectFilePath(parent, path, dummy); 5729c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result != MTP_RESPONSE_OK) 5739c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 57416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 57516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 57616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 57716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 57816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 57916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 58016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 58116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 58216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 58316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 58416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 58516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 58616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 58716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 58816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 58916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 59016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 59116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 59216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 59316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 59416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 59516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 59616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 59716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 598fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 59916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 60016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 60116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 60216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 60316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 60416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 60516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 6064714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path, 6074714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood format, parent, storageID, mSendObjectFileSize, modifiedTime); 608fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 60916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 610fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 61116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 61216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 61316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 6148e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood int ret = mkdir((const char *)path, mDirectoryPermission); 61516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 61616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 61716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 6188e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood chown((const char *)path, getuid(), mFileGroup); 61916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 62016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 62116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 62216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 6234714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = format; 62416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 62516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 62616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 6271865a5ddcfe7b0e8dc211419aea1094b1491a5fdMike Lockwood mResponse.setParameter(2, (parent == 0 ? 0xFFFFFFFF: parent)); 62816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 62916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 63016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 63116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 63216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 63316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 6344714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood MtpResponseCode result = MTP_RESPONSE_OK; 6354714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mode_t mask; 6364714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood int ret; 6374714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 63816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 639b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGE("Expected SendObjectInfo before SendObject"); 6404714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_NO_VALID_OBJECT_INFO; 6414714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 64216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 64316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 64416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read the header 6454714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood ret = mData.readDataHeader(mFD); 64616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 64716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 64816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // reset so we don't attempt to send this back 64916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 65016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 65116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 652c6588763ddc20541688e426a24b1b070527c051fMike Lockwood mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC); 653c6588763ddc20541688e426a24b1b070527c051fMike Lockwood if (mfr.fd < 0) { 6544714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 6554714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood goto done; 656c6588763ddc20541688e426a24b1b070527c051fMike Lockwood } 6578e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchown(mfr.fd, getuid(), mFileGroup); 6588e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood // set permissions 6594714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mask = umask(0); 6608e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood fchmod(mfr.fd, mFilePermission); 6618e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood umask(mask); 6628e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 66316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 66416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = mSendObjectFileSize; 66516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 66616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // transfer the file 66716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 668c6588763ddc20541688e426a24b1b070527c051fMike Lockwood close(mfr.fd); 6698e2a280ab7f98bf00ff2651f1f93c8f8bd46c08dMike Lockwood 670b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood LOGV("MTP_RECEIVE_FILE returned %d", ret); 67116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 672916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (ret < 0) { 673916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood unlink(mSendObjectFilePath); 674916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood if (errno == ECANCELED) 6754714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_TRANSACTION_CANCELLED; 676916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood else 6774714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result = MTP_RESPONSE_GENERAL_ERROR; 678916076c6d84dac9b104fbdf94af5dcd7bce669fdMike Lockwood } 6794714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood 6804714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwooddone: 6814714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, 6824714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood result == MTP_RESPONSE_OK); 6834714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 6844714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood mSendObjectFormat = 0; 6854714b0766ecf48f09f39b4781a5c4deafc092d49Mike Lockwood return result; 68616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 68716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 68816864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 68916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 69016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 69116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 69216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 69316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - handle non-empty directories 69416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 69516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 69616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 6979c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood int result = mDatabase->getObjectFilePath(handle, filePath, fileLength); 6989c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood if (result == MTP_RESPONSE_OK) { 6999c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood LOGV("deleting %s", (const char *)filePath); 7009c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood // one of these should work 7019c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood rmdir((const char *)filePath); 7029c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood unlink((const char *)filePath); 7039c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return mDatabase->deleteFile(handle); 7049c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } else { 7059c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood return result; 7069c04c4cc038f924d9cb98798e1c07fe6017e85d0Mike Lockwood } 70716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 70816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 70916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 71021ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpObjectProperty propCode = mRequest.getParameter(1); 71116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 71221ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood MtpProperty* property = getObjectProperty(propCode); 71321ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood if (!property) 71421ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 71516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 71621ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood property->write(mData); 71721ef7d0e70c5ad599bc2602cb484f8cd647055caMike Lockwood return MTP_RESPONSE_OK; 71816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 7197850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 7207850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 721