MtpServer.cpp revision fceef46513db3507b413f604cea89e3c7f352663
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 2516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDebug.h" 2616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpServer.h" 2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStorage.h" 2816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpStringBuffer.h" 2916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "MtpDatabase.h" 3016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 3116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include "f_mtp.h" 3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 337850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android { 347850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpOperationCode kSupportedOperationCodes[] = { 3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_INFO, 3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_OPEN_SESSION, 3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_CLOSE_SESSION, 3916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_IDS, 4016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_STORAGE_INFO, 4116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_NUM_OBJECTS, 4216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_HANDLES, 4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_INFO, 4416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT, 4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_THUMB, 4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_DELETE_OBJECT, 4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT_INFO, 4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SEND_OBJECT, 4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_CAPTURE, 5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_FORMAT_STORE, 5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_RESET_DEVICE, 5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SELF_TEST, 5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_PROTECTION, 5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_POWER_DOWN, 5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_DESC, 5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_DEVICE_PROP_VALUE, 5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SET_DEVICE_PROP_VALUE, 5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_RESET_DEVICE_PROP_VALUE, 5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_TERMINATE_OPEN_CAPTURE, 6016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_MOVE_OBJECT, 6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_COPY_OBJECT, 6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_PARTIAL_OBJECT, 6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_INITIATE_OPEN_CAPTURE, 6416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED, 6516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_OBJECT_PROP_DESC, 6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_GET_OBJECT_PROP_VALUE, 6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_OPERATION_SET_OBJECT_PROP_VALUE, 6816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_GET_OBJECT_REFERENCES, 6916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SET_OBJECT_REFERENCES, 7016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood// MTP_OPERATION_SKIP, 7116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 7316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpObjectProperty kSupportedObjectProperties[] = { 7416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_STORAGE_ID, 7516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_FORMAT, 7616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_SIZE, 7716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_OBJECT_FILE_NAME, 7816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_PROPERTY_PARENT_OBJECT, 7916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 8016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 8116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodstatic const MtpObjectFormat kSupportedPlaybackFormats[] = { 82fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_UNDEFINED, 8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_FORMAT_ASSOCIATION, 84fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_TEXT, 85fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_HTML, 8616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MTP_FORMAT_MP3, 87fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood //MTP_FORMAT_AVI, 88fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MPEG, 89fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_ASF, 90fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_EXIF_JPEG, 91fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_TIFF_EP, 92fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_BMP, 93fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_GIF, 94fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_JFIF, 95fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_PNG, 96fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_TIFF, 97fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_WMA, 98fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_OGG, 99fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_AAC, 100fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_FLAC, 101fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_WMV, 102fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MP4_CONTAINER, 103fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_MP2, 104fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MTP_FORMAT_3GP_CONTAINER, 105fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_ABSTRACT_AUDIO_ALBUM, 106fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_ABSTRACT_AV_PLAYLIST, 107fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_WPL_PLAYLIST, 108fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_M3U_PLAYLIST, 109fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_MPL_PLAYLIST, 110fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood // MTP_FORMAT_PLS_PLAYLIST, 11116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}; 11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 11316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::MtpServer(int fd, const char* databasePath) 11416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood : mFD(fd), 11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mDatabasePath(databasePath), 11616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mDatabase(NULL), 11716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID(0), 11816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen(false), 11916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle(kInvalidObjectHandle), 12016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize(0) 12116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{ 12216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mDatabase = new MtpDatabase(); 12316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mDatabase->open(databasePath, true); 12416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 12516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 12616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpServer::~MtpServer() { 12716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 12816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 12916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::addStorage(const char* filePath) { 13016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int index = mStorages.size() + 1; 13116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood index |= index << 16; // set high and low part to our index 13216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = new MtpStorage(index, filePath, mDatabase); 13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood addStorage(storage); 13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 13616864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpStorage* MtpServer::getStorage(MtpStorageID id) { 13716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = mStorages[i]; 13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (storage->getStorageID() == id) 14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return storage; 14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return NULL; 14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 14516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::scanStorage() { 14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < mStorages.size(); i++) { 14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = mStorages[i]; 14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood storage->scanFiles(); 14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 15116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::run() { 15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int fd = mFD; 15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("MtpServer::run fd: %d\n", fd); 15616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 15716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood while (1) { 15816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mRequest.read(fd); 15916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 16016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "request read returned %d, errno: %d\n", ret, errno); 16116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 16216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 16316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 16416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpTransactionID transaction = mRequest.getTransactionID(); 16516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("operation: %s\n", MtpDebug::getOperationCodeName(operation)); 16716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mRequest.dump(); 16816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 16916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME need to generalize this 17016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO); 17116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (dataIn) { 17216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.read(fd); 17316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 17416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "data read returned %d, errno: %d\n", ret, errno); 17516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 17616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 17716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("received data:\n"); 17816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 17916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 18016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 18116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 18216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 18316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood handleRequest(); 18416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 18516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!dataIn && mData.hasData()) { 18616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(operation); 18716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(transaction); 18816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("sending data:\n"); 18916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.dump(); 19016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = mData.write(fd); 19116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 19216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "request write returned %d, errno: %d\n", ret, errno); 19316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 19416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 19616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 19716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setTransactionID(transaction); 19816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = mResponse.write(fd); 19916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret < 0) { 20016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "request write returned %d, errno: %d\n", ret, errno); 20116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 20216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 20316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 20416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 20516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 20616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpServer::handleRequest() { 20716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpOperationCode operation = mRequest.getOperationCode(); 20816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpResponseCode response; 20916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 21016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.reset(); 21116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 21216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) { 21316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - need to delete mSendObjectHandle from the database 21416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "expected SendObject after SendObjectInfo\n"); 21516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 21616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 21716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 21816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood switch (operation) { 21916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_DEVICE_INFO: 22016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetDeviceInfo(); 22116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_OPEN_SESSION: 22316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doOpenSession(); 22416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_CLOSE_SESSION: 22616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doCloseSession(); 22716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 22816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_IDS: 22916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageIDs(); 23016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 23116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_STORAGE_INFO: 23216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetStorageInfo(); 23316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 23416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED: 23516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropsSupported(); 23616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 23716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_HANDLES: 23816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectHandles(); 23916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 24016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_VALUE: 24116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectPropValue(); 24216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 24316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_INFO: 24416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObjectInfo(); 24516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 24616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT: 24716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doGetObject(); 24816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 24916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT_INFO: 25016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObjectInfo(); 25116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 25216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_SEND_OBJECT: 25316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doSendObject(); 25416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 25516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_DELETE_OBJECT: 25616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = doDeleteObject(); 25716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 25816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood case MTP_OPERATION_GET_OBJECT_PROP_DESC: 25916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood default: 26016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED; 26116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood break; 26216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 26316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 26416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setResponseCode(response); 26516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 26616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 26716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetDeviceInfo() { 26816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 26916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 27016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // fill in device info 27116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 27216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(6); // MTP Vendor Extension ID 27316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(MTP_STANDARD_VERSION); 27416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("microsoft.com: 1.0;"); 27516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // MTP Extensions 27616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(0); //Functional Mode 27716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedOperationCodes, 27816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported 27916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyArray(); // Events Supported 28016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyArray(); // Device Properties Supported 28116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyArray(); // Capture Formats 28216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedPlaybackFormats, 28316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedPlaybackFormats) / sizeof(uint16_t)); // Playback Formats 28416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME 28516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("Google, Inc."); 28616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Manufacturer 28716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("Just an Ordinary MTP Device"); 28816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Model 28916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("1.0"); 29016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Device Version 29116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set("123456789012345678AA"); 29216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); // Serial Number 29316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 29416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 29516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 29616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 29716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doOpenSession() { 29816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSessionOpen) { 29916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, mSessionID); 30016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_ALREADY_OPEN; 30116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 30216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = mRequest.getParameter(1); 30316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = true; 30416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 30516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 30616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 30716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doCloseSession() { 30816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 30916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 31016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionID = 0; 31116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSessionOpen = false; 31216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 31316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 31416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageIDs() { 31616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 31716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 31816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 31916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int count = mStorages.size(); 32016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(count); 32116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood for (int i = 0; i < count; i++) 32216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(mStorages[i]->getStorageID()); 32316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 32516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 32616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 32716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetStorageInfo() { 32816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer string; 32916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 33016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 33116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 33216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID id = mRequest.getParameter(1); 33316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(id); 33416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 33516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 33616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 33716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getType()); 33816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getFileSystemType()); 33916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt16(storage->getAccessCapability()); 34016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getMaxCapacity()); 34116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt64(storage->getFreeSpace()); 34216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putUInt32(1024*1024*1024); // Free Space in Objects 34316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood string.set(storage->getDescription()); 34416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putString(string); 34516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putEmptyString(); // Volume Identifier 34616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 34716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 34816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 34916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 35016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropsSupported() { 35116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 35216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 35316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 35416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt16(kSupportedObjectProperties, 35516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood sizeof(kSupportedObjectProperties) / sizeof(uint16_t)); 35616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 35716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 35816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 35916864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectHandles() { 36016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mSessionOpen) 36116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_SESSION_NOT_OPEN; 36216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage 36316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); // 0x00000000 for all formats 36416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent 36516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // 0x00000000 for all objects? 36616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 36716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); 36816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.putAUInt32(handles); 36916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood delete handles; 37016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 37116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 37216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 37316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropValue() { 37416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 37516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(2); 37616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 37716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return mDatabase->getObjectProperty(handle, property, mData); 37816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 37916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 38016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectInfo() { 38116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 38216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return mDatabase->getObjectInfo(handle, mData); 38316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 38416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 38516864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObject() { 38616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 38716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 38816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 38916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mDatabase->getObjectFilePath(handle, filePath, fileLength)) 39016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 39116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 39216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 39316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.path = filePath; 39416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.path_length = strlen(mfr.path); 39516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 39616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = fileLength; 39716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 39816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // send data header 39916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setOperationCode(mRequest.getOperationCode()); 40016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.setTransactionID(mRequest.getTransactionID()); 40116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.writeDataHeader(mFD, fileLength); 40216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 40316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // then transfer the file 40416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = ioctl(mFD, MTP_SEND_FILE, (unsigned long)&mfr); 40516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here 40616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("MTP_SEND_FILE returned %d\n", ret); 40716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 40816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 40916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObjectInfo() { 41116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString path; 41216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorageID storageID = mRequest.getParameter(1); 41316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStorage* storage = getStorage(storageID); 41416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle parent = mRequest.getParameter(2); 41516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!storage) 41616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_STORAGE_ID; 41716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 41816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // special case the root 41916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (parent == MTP_PARENT_ROOT) 42016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path = storage->getPath(); 42116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood else { 42216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t dummy; 42316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mDatabase->getObjectFilePath(parent, path, dummy)) 42416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 42516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 42616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 42716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read only the fields we need 42816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // storage ID 42916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mData.getUInt16(); 43016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // protection status 43116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFileSize = mData.getUInt32(); 43216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt16(); // thumb format 43316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb compressed size 43416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix width 43516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // thumb pix height 43616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix width 43716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image pix height 43816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // image bit depth 43916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // parent 44016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint16_t associationType = mData.getUInt16(); 44116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood uint32_t associationDesc = mData.getUInt32(); // association desc 44216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getUInt32(); // sequence number 44316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpStringBuffer name, created, modified; 44416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(name); // file name 44516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(created); // date created 44616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.getString(modified); // date modified 44716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // keywords follow 44816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 449fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood time_t modifiedTime; 45016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!parseDateTime(modified, modifiedTime)) 45116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood modifiedTime = 0; 45216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodprintf("SendObjectInfo format: %04X size: %d name: %s, created: %s, modified: %s\n", 45316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodformat, mSendObjectFileSize, (const char*)name, (const char*)created, (const char*)modified); 45416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 45516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (path[path.size() - 1] != '/') 45616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += "/"; 45716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood path += (const char *)name; 45816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 459fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood mDatabase->beginTransaction(); 460fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood MtpObjectHandle handle = mDatabase->addFile((const char*)path, format, parent, storageID, 461fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood mSendObjectFileSize, modifiedTime); 462fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (handle == kInvalidObjectHandle) { 463fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood mDatabase->rollbackTransaction(); 46416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 465fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood } 466fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood uint32_t table = MtpDatabase::getTableForFile(format); 467fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood if (table == kObjectHandleTableAudio) 468fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood handle = mDatabase->addAudioFile(handle); 469fceef46513db3507b413f604cea89e3c7f352663Mike Lockwood mDatabase->commitTransaction(); 47016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 47116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (format == MTP_FORMAT_ASSOCIATION) { 47216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mode_t mask = umask(0); 47316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mkdir((const char *)path, S_IRWXU | S_IRWXG | S_IRWXO); 47416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood umask(mask); 47516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (ret && ret != -EEXIST) 47616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 47716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } else { 47816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectFilePath = path; 47916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // save the handle for the SendObject call, which should follow 48016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = handle; 48116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 48216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 48316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(1, storageID); 48416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(2, parent); 48516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mResponse.setParameter(3, handle); 48616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 48716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 48816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 48916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49016864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doSendObject() { 49116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (mSendObjectHandle == kInvalidObjectHandle) { 49216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood fprintf(stderr, "Expected SendObjectInfo before SendObject\n"); 49316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_NO_VALID_OBJECT_INFO; 49416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood } 49516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 49616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // read the header 49716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int ret = mData.readDataHeader(mFD); 49816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 49916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // reset so we don't attempt to send this back 50116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mData.reset(); 50216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mtp_file_range mfr; 50416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.path = (const char*)mSendObjectFilePath; 50516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.path_length = strlen(mfr.path); 50616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.offset = 0; 50716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mfr.length = mSendObjectFileSize; 50816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 50916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // transfer the file 51016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); 51116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - check for errors here. 51216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // we need to return a reasonable response and delete 51316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // mSendObjectHandle from the database if this fails. 51416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood printf("MTP_RECEIVE_FILE returned %d\n", ret); 51516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mSendObjectHandle = kInvalidObjectHandle; 51716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 51816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 51916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 52016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doDeleteObject() { 52216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectHandle handle = mRequest.getParameter(1); 52316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(1); 52416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - support deleting all objects if handle is 0xFFFFFFFF 52516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - implement deleting objects by format 52616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // FIXME - handle non-empty directories 52716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 52816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpString filePath; 52916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood int64_t fileLength; 53016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood if (!mDatabase->getObjectFilePath(handle, filePath, fileLength)) 53116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 53216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodprintf("deleting %s\n", (const char *)filePath); 53416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood // one of these should work 53516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood rmdir((const char *)filePath); 53616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood unlink((const char *)filePath); 53716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 53816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood mDatabase->deleteFile(handle); 53916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return MTP_RESPONSE_OK; 54116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 54216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54316864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpResponseCode MtpServer::doGetObjectPropDesc() { 54416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectProperty property = mRequest.getParameter(1); 54516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood MtpObjectFormat format = mRequest.getParameter(2); 54616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood 54716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood return -1; 54816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood} 5497850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood 5507850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood} // namespace android 551