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