summaryrefslogtreecommitdiffstats
path: root/mtp/mtp_MtpDatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xmtp/mtp_MtpDatabase.cpp884
1 files changed, 884 insertions, 0 deletions
diff --git a/mtp/mtp_MtpDatabase.cpp b/mtp/mtp_MtpDatabase.cpp
new file mode 100755
index 000000000..60a871ce3
--- /dev/null
+++ b/mtp/mtp_MtpDatabase.cpp
@@ -0,0 +1,884 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
+ */
+
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string>
+#include <map>
+#include <libgen.h>
+#include <cutils/properties.h>
+
+#include "MtpDatabase.h"
+#include "MtpStorage.h"
+#include "MtpDataPacket.h"
+#include "MtpObjectInfo.h"
+#include "MtpProperty.h"
+#include "MtpDebug.h"
+#include "MtpStringBuffer.h"
+#include "MtpUtils.h"
+#include "mtp.h"
+#include "mtp_MtpDatabase.hpp"
+#include "btree.hpp"
+
+MyMtpDatabase::MyMtpDatabase()
+{
+ storagenum = 0;
+ count = -1;
+}
+
+MyMtpDatabase::~MyMtpDatabase() {
+ std::map<int, MtpStorage*>::iterator i;
+ for (i = storagemap.begin(); i != storagemap.end(); i++) {
+ delete i->second;
+ }
+}
+
+int MyMtpDatabase::FILE_PROPERTIES[10] = {
+ // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
+ // and IMAGE_PROPERTIES below
+ MTP_PROPERTY_STORAGE_ID,
+ MTP_PROPERTY_OBJECT_FORMAT,
+ MTP_PROPERTY_PROTECTION_STATUS,
+ MTP_PROPERTY_OBJECT_SIZE,
+ MTP_PROPERTY_OBJECT_FILE_NAME,
+ MTP_PROPERTY_DATE_MODIFIED,
+ MTP_PROPERTY_PARENT_OBJECT,
+ MTP_PROPERTY_PERSISTENT_UID,
+ MTP_PROPERTY_NAME,
+ MTP_PROPERTY_DATE_ADDED
+};
+int MyMtpDatabase::AUDIO_PROPERTIES[19] = {
+ // NOTE must match FILE_PROPERTIES above
+ MTP_PROPERTY_STORAGE_ID,
+ MTP_PROPERTY_OBJECT_FORMAT,
+ MTP_PROPERTY_PROTECTION_STATUS,
+ MTP_PROPERTY_OBJECT_SIZE,
+ MTP_PROPERTY_OBJECT_FILE_NAME,
+ MTP_PROPERTY_DATE_MODIFIED,
+ MTP_PROPERTY_PARENT_OBJECT,
+ MTP_PROPERTY_PERSISTENT_UID,
+ MTP_PROPERTY_NAME,
+ MTP_PROPERTY_DISPLAY_NAME,
+ MTP_PROPERTY_DATE_ADDED,
+
+ // audio specific properties
+ MTP_PROPERTY_ARTIST,
+ MTP_PROPERTY_ALBUM_NAME,
+ MTP_PROPERTY_ALBUM_ARTIST,
+ MTP_PROPERTY_TRACK,
+ MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
+ MTP_PROPERTY_DURATION,
+ MTP_PROPERTY_GENRE,
+ MTP_PROPERTY_COMPOSER
+};
+
+int MyMtpDatabase::VIDEO_PROPERTIES[15] = {
+ // NOTE must match FILE_PROPERTIES above
+ MTP_PROPERTY_STORAGE_ID,
+ MTP_PROPERTY_OBJECT_FORMAT,
+ MTP_PROPERTY_PROTECTION_STATUS,
+ MTP_PROPERTY_OBJECT_SIZE,
+ MTP_PROPERTY_OBJECT_FILE_NAME,
+ MTP_PROPERTY_DATE_MODIFIED,
+ MTP_PROPERTY_PARENT_OBJECT,
+ MTP_PROPERTY_PERSISTENT_UID,
+ MTP_PROPERTY_NAME,
+ MTP_PROPERTY_DISPLAY_NAME,
+ MTP_PROPERTY_DATE_ADDED,
+
+ // video specific properties
+ MTP_PROPERTY_ARTIST,
+ MTP_PROPERTY_ALBUM_NAME,
+ MTP_PROPERTY_DURATION,
+ MTP_PROPERTY_DESCRIPTION
+};
+
+int MyMtpDatabase::IMAGE_PROPERTIES[12] = {
+ // NOTE must match FILE_PROPERTIES above
+ MTP_PROPERTY_STORAGE_ID,
+ MTP_PROPERTY_OBJECT_FORMAT,
+ MTP_PROPERTY_PROTECTION_STATUS,
+ MTP_PROPERTY_OBJECT_SIZE,
+ MTP_PROPERTY_OBJECT_FILE_NAME,
+ MTP_PROPERTY_DATE_MODIFIED,
+ MTP_PROPERTY_PARENT_OBJECT,
+ MTP_PROPERTY_PERSISTENT_UID,
+ MTP_PROPERTY_NAME,
+ MTP_PROPERTY_DISPLAY_NAME,
+ MTP_PROPERTY_DATE_ADDED,
+
+ // image specific properties
+ MTP_PROPERTY_DESCRIPTION
+};
+
+int MyMtpDatabase::ALL_PROPERTIES[25] = {
+ // NOTE must match FILE_PROPERTIES above
+ MTP_PROPERTY_STORAGE_ID,
+ MTP_PROPERTY_OBJECT_FORMAT,
+ MTP_PROPERTY_PROTECTION_STATUS,
+ MTP_PROPERTY_OBJECT_SIZE,
+ MTP_PROPERTY_OBJECT_FILE_NAME,
+ MTP_PROPERTY_DATE_MODIFIED,
+ MTP_PROPERTY_PARENT_OBJECT,
+ MTP_PROPERTY_PERSISTENT_UID,
+ MTP_PROPERTY_NAME,
+ MTP_PROPERTY_DISPLAY_NAME,
+ MTP_PROPERTY_DATE_ADDED,
+
+ // image specific properties
+ MTP_PROPERTY_DESCRIPTION,
+
+ // audio specific properties
+ MTP_PROPERTY_ARTIST,
+ MTP_PROPERTY_ALBUM_NAME,
+ MTP_PROPERTY_ALBUM_ARTIST,
+ MTP_PROPERTY_TRACK,
+ MTP_PROPERTY_ORIGINAL_RELEASE_DATE,
+ MTP_PROPERTY_DURATION,
+ MTP_PROPERTY_GENRE,
+ MTP_PROPERTY_COMPOSER,
+
+ // video specific properties
+ MTP_PROPERTY_ARTIST,
+ MTP_PROPERTY_ALBUM_NAME,
+ MTP_PROPERTY_DURATION,
+ MTP_PROPERTY_DESCRIPTION,
+
+ // image specific properties
+ MTP_PROPERTY_DESCRIPTION
+};
+
+int MyMtpDatabase::SUPPORTED_PLAYBACK_FORMATS[26] = {
+ SUPPORTED_PLAYBACK_FORMAT_UNDEFINED,
+ SUPPORTED_PLAYBACK_FORMAT_ASSOCIATION,
+ SUPPORTED_PLAYBACK_FORMAT_TEXT,
+ SUPPORTED_PLAYBACK_FORMAT_HTML,
+ SUPPORTED_PLAYBACK_FORMAT_WAV,
+ SUPPORTED_PLAYBACK_FORMAT_MP3,
+ SUPPORTED_PLAYBACK_FORMAT_MPEG,
+ SUPPORTED_PLAYBACK_FORMAT_EXIF_JPEG,
+ SUPPORTED_PLAYBACK_FORMAT_TIFF_EP,
+ SUPPORTED_PLAYBACK_FORMAT_BMP,
+ SUPPORTED_PLAYBACK_FORMAT_GIF,
+ SUPPORTED_PLAYBACK_FORMAT_JFIF,
+ SUPPORTED_PLAYBACK_FORMAT_PNG,
+ SUPPORTED_PLAYBACK_FORMAT_TIFF,
+ SUPPORTED_PLAYBACK_FORMAT_WMA,
+ SUPPORTED_PLAYBACK_FORMAT_OGG,
+ SUPPORTED_PLAYBACK_FORMAT_AAC,
+ SUPPORTED_PLAYBACK_FORMAT_MP4_CONTAINER,
+ SUPPORTED_PLAYBACK_FORMAT_MP2,
+ SUPPORTED_PLAYBACK_FORMAT_3GP_CONTAINER,
+ SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AV_PLAYLIST,
+ SUPPORTED_PLAYBACK_FORMAT_WPL_PLAYLIST,
+ SUPPORTED_PLAYBACK_FORMAT_M3U_PLAYLIST,
+ SUPPORTED_PLAYBACK_FORMAT_PLS_PLAYLIST,
+ SUPPORTED_PLAYBACK_FORMAT_XML_DOCUMENT,
+ SUPPORTED_PLAYBACK_FORMAT_FLAC
+};
+
+MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
+ MtpObjectFormat format,
+ MtpObjectHandle parent,
+ MtpStorageID storage,
+ uint64_t size,
+ time_t modified) {
+ MTPD("MyMtpDatabase::beginSendObject() which passes to MtpStorage.cpp\n");
+ return storagemap[storage]->beginSendObject(path, format, parent, storage, size, modified);
+}
+
+void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
+ MtpObjectFormat format, bool succeeded) {
+ MTPD("endSendObject() %s\n", path);
+ if (!succeeded) {
+ MTPE("endSendObject() failed, unlinking %s\n", path);
+ unlink(path);
+ }
+}
+
+void MyMtpDatabase::createDB(MtpStorage* storage, MtpStorageID storageID) {
+ storagemap[storageID] = storage;
+ storage->createDB();
+}
+
+MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
+ MtpObjectFormat format,
+ MtpObjectHandle parent) {
+ MTPD("storageID: %d\n", storageID);
+ MtpObjectHandleList* list = new MtpObjectHandleList();
+ list = storagemap[storageID]->getObjectList(storageID, parent);
+ MTPD("list: %d\n", list->size());
+ return list;
+}
+
+int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
+ MtpObjectFormat format,
+ MtpObjectHandle parent) {
+ MTPE("MyMtpDatabase::getNumObjects not implemented, returning 0\n");
+ int result = 0;
+ //get number of objects on filesystem storage
+ return result;
+}
+
+MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
+ // This function tells the host PC which file formats the device supports
+ int* formats;
+ MtpObjectFormatList* list = new MtpObjectFormatList();
+ formats = SUPPORTED_PLAYBACK_FORMATS;
+ int length = sizeof(formats)/ sizeof(int);
+ MTPD("MyMtpDatabase::getSupportedPlaybackFormats length: %i\n", length);
+ for (int i = 0; i < length; i++) {
+ MTPD("supported playback format: %d\n", formats[i]);
+ list->push(formats[i]);
+ }
+ return list;
+}
+
+MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
+ // Android OS implementation of this function returns NULL
+ // so we are not implementing this function either.
+ MTPD("MyMtpDatabase::getSupportedCaptureFormats returning NULL (This is what Android does as well).\n");
+ return NULL;
+}
+
+MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
+ int* properties;
+ MtpObjectPropertyList* list = new MtpObjectPropertyList();
+ properties = FILE_PROPERTIES;
+ int length = sizeof(FILE_PROPERTIES);
+ MTPD("MyMtpDatabase::getSupportedObjectProperties length is: %i, format: %x, sizeof: %i, forcing length to 10\n", length, format, sizeof(properties));
+ for (int i = 0; i < length; i++) {
+ MTPD("supported object property: %x\n", properties[i]);
+ list->push(properties[i]);
+ }
+ return list;
+}
+
+MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
+ int properties[] = {
+ MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
+ MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
+ MTP_DEVICE_PROPERTY_IMAGE_SIZE,
+ };
+ MtpDevicePropertyList* list = new MtpDevicePropertyList();
+ int length = sizeof(properties) / sizeof(int);
+ MTPD("MyMtpDatabase::getSupportedDeviceProperties length was: %i, forcing to 3\n", length);
+ length = 3;
+ for (int i = 0; i < length; i++)
+ list->push(properties[i]);
+ return list;
+}
+
+int* MyMtpDatabase::getSupportedObjectProperties(int format) {
+ switch (format) {
+ case MTP_FORMAT_MP3:
+ case MTP_FORMAT_WAV:
+ case MTP_FORMAT_WMA:
+ case MTP_FORMAT_OGG:
+ case MTP_FORMAT_AAC:
+ return AUDIO_PROPERTIES;
+ case MTP_FORMAT_MPEG:
+ case MTP_FORMAT_3GP_CONTAINER:
+ case MTP_FORMAT_WMV:
+ return VIDEO_PROPERTIES;
+ case MTP_FORMAT_EXIF_JPEG:
+ case MTP_FORMAT_GIF:
+ case MTP_FORMAT_PNG:
+ case MTP_FORMAT_BMP:
+ return IMAGE_PROPERTIES;
+ case 0:
+ return ALL_PROPERTIES;
+ default:
+ return FILE_PROPERTIES;
+ }
+}
+
+MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) {
+ MTPD("MyMtpDatabase::getObjectPropertyValue mtpid: %i, property: %x\n", handle, property);
+ int type;
+ MtpResponseCode result;
+ uint64_t longValue;
+ if (!getObjectPropertyInfo(property, type)) {
+ MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
+ return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+ }
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ if (storit->second->getObjectPropertyValue(handle, property, longValue) == 0) {
+ result = MTP_RESPONSE_OK;
+ break;
+ }
+ }
+
+ // special case date properties, which are strings to MTP
+ // but stored internally as a uint64
+ if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
+ char date[20];
+ formatDateTime(longValue, date, sizeof(date));
+ packet.putString(date);
+ goto out;
+ }
+ // release date is stored internally as just the year
+ if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
+ char date[20];
+ snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
+ packet.putString(date);
+ goto out;
+ }
+
+ switch (type) {
+ case MTP_TYPE_INT8:
+ packet.putInt8(longValue);
+ break;
+ case MTP_TYPE_UINT8:
+ packet.putUInt8(longValue);
+ break;
+ case MTP_TYPE_INT16:
+ packet.putInt16(longValue);
+ break;
+ case MTP_TYPE_UINT16:
+ packet.putUInt16(longValue);
+ break;
+ case MTP_TYPE_INT32:
+ packet.putInt32(longValue);
+ break;
+ case MTP_TYPE_UINT32:
+ packet.putUInt32(longValue);
+ break;
+ case MTP_TYPE_INT64:
+ packet.putInt64(longValue);
+ break;
+ case MTP_TYPE_UINT64:
+ packet.putUInt64(longValue);
+ break;
+ case MTP_TYPE_INT128:
+ packet.putInt128(longValue);
+ break;
+ case MTP_TYPE_UINT128:
+ packet.putInt128(longValue);
+ break;
+ case MTP_TYPE_STR:
+ {
+ /*std::string stringValue = (string)stringValuesArray[0];
+ if (stringValue) {
+ const char* str = stringValue.c_str();
+ if (str == NULL) {
+ return MTP_RESPONSE_GENERAL_ERROR;
+ }
+ packet.putString(str);
+ } else {
+ packet.putEmptyString();
+ }*/
+ MTPE("STRING unsupported type in getObjectPropertyValue\n");
+ result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+ break;
+ }
+ default:
+ MTPE("unsupported type in getObjectPropertyValue\n");
+ result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+ }
+out:
+ return result;
+}
+
+MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
+ MtpObjectProperty property,
+ MtpDataPacket& packet) {
+ int type;
+ MTPD("MyMtpDatabase::setObjectPropertyValue start\n");
+ if (!getObjectPropertyInfo(property, type)) {
+ MTPE("MyMtpDatabase::setObjectPropertyValue returning MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED\n");
+ return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+ }
+ MTPD("MyMtpDatabase::setObjectPropertyValue continuing\n");
+ long longValue = 0;
+ std::string stringValue;
+
+ switch (type) {
+ case MTP_TYPE_INT8:
+ MTPD("int8\n");
+ longValue = packet.getInt8();
+ break;
+ case MTP_TYPE_UINT8:
+ MTPD("uint8\n");
+ longValue = packet.getUInt8();
+ break;
+ case MTP_TYPE_INT16:
+ MTPD("int16\n");
+ longValue = packet.getInt16();
+ break;
+ case MTP_TYPE_UINT16:
+ MTPD("uint16\n");
+ longValue = packet.getUInt16();
+ break;
+ case MTP_TYPE_INT32:
+ MTPD("int32\n");
+ longValue = packet.getInt32();
+ break;
+ case MTP_TYPE_UINT32:
+ MTPD("uint32\n");
+ longValue = packet.getUInt32();
+ break;
+ case MTP_TYPE_INT64:
+ MTPD("int64\n");
+ longValue = packet.getInt64();
+ break;
+ case MTP_TYPE_UINT64:
+ MTPD("uint64\n");
+ longValue = packet.getUInt64();
+ break;
+ case MTP_TYPE_STR:
+ {
+ MTPD("string\n");
+ MtpStringBuffer buffer;
+ packet.getString(buffer);
+ stringValue = (const char *)buffer;
+ break;
+ }
+ default:
+ MTPE("MyMtpDatabase::setObjectPropertyValue unsupported type %i in getObjectPropertyValue\n", type);
+ return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
+ }
+
+ int result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+
+ switch (property) {
+ case MTP_PROPERTY_OBJECT_FILE_NAME:
+ {
+ MTPD("MyMtpDatabase::setObjectPropertyValue renaming file, handle: %d, new name: '%s'\n", handle, stringValue.c_str());
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ if (storit->second->renameObject(handle, stringValue) == 0) {
+ MTPD("MTP_RESPONSE_OK\n");
+ result = MTP_RESPONSE_OK;
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ MTPE("MyMtpDatabase::setObjectPropertyValue property %x not supported.\n", property);
+ result = MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
+ }
+ MTPD("MyMtpDatabase::setObjectPropertyValue returning %d\n", result);
+ return result;
+}
+
+MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
+ MtpDataPacket& packet) {
+ int type, result = 0;
+ char prop_value[PROPERTY_VALUE_MAX];
+ MTPD("property %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+ if (!getDevicePropertyInfo(property, type)) {
+ MTPE("MyMtpDatabase::getDevicePropertyValue MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED\n");
+ return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+ }
+ MTPD("property %s\n",
+ MtpDebug::getDevicePropCodeName(property));
+ MTPD("property %x\n", property);
+ MTPD("MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME %x\n", MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME);
+ switch (property) {
+ case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
+ case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+ result = MTP_RESPONSE_OK;
+ break;
+ default:
+ {
+ MTPE("MyMtpDatabase::getDevicePropertyValue property %x not supported\n", property);
+ result = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+ break;
+ }
+ }
+
+ if (result != MTP_RESPONSE_OK) {
+ MTPD("MTP_REPONSE_OK NOT OK\n");
+ return result;
+ }
+
+ long longValue = 0;
+ property_get("ro.build.product", prop_value, "unknown manufacturer");
+ switch (type) {
+ case MTP_TYPE_INT8: {
+ MTPD("MTP_TYPE_INT8\n");
+ packet.putInt8(longValue);
+ break;
+ }
+ case MTP_TYPE_UINT8:
+ {
+ MTPD("MTP_TYPE_UINT8\n");
+ packet.putUInt8(longValue);
+ break;
+ }
+ case MTP_TYPE_INT16:
+ {
+ MTPD("MTP_TYPE_INT16\n");
+ packet.putInt16(longValue);
+ break;
+ }
+ case MTP_TYPE_UINT16:
+ {
+ MTPD("MTP_TYPE_UINT16\n");
+ packet.putUInt16(longValue);
+ break;
+ }
+ case MTP_TYPE_INT32:
+ {
+ MTPD("MTP_TYPE_INT32\n");
+ packet.putInt32(longValue);
+ break;
+ }
+ case MTP_TYPE_UINT32:
+ {
+ MTPD("MTP_TYPE_UINT32\n");
+ packet.putUInt32(longValue);
+ break;
+ }
+ case MTP_TYPE_INT64:
+ {
+ MTPD("MTP_TYPE_INT64\n");
+ packet.putInt64(longValue);
+ break;
+ }
+ case MTP_TYPE_UINT64:
+ {
+ MTPD("MTP_TYPE_UINT64\n");
+ packet.putUInt64(longValue);
+ break;
+ }
+ case MTP_TYPE_INT128:
+ {
+ MTPD("MTP_TYPE_INT128\n");
+ packet.putInt128(longValue);
+ break;
+ }
+ case MTP_TYPE_UINT128:
+ {
+ MTPD("MTP_TYPE_UINT128\n");
+ packet.putInt128(longValue);
+ break;
+ }
+ case MTP_TYPE_STR:
+ {
+ MTPD("MTP_TYPE_STR\n");
+ char* str = prop_value;
+ packet.putString(str);
+ break;
+ }
+ default:
+ MTPE("MyMtpDatabase::getDevicePropertyValue unsupported type %i in getDevicePropertyValue\n", type);
+ return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
+ }
+
+ return MTP_RESPONSE_OK;
+}
+
+MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property, MtpDataPacket& packet) {
+ int type;
+ MTPE("MyMtpDatabase::setDevicePropertyValue not implemented, returning 0\n");
+ return 0;
+}
+
+MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
+ MTPE("MyMtpDatabase::resetDeviceProperty not implemented, returning -1\n");
+ return -1;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
+ MTPD("getObjectPropertyList()\n");
+ MTPD("property: %x\n", property);
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ MTPD("MyMtpDatabase::getObjectPropertyList calling getObjectPropertyList\n");
+ if (storit->second->getObjectPropertyList(handle, format, property, groupCode, depth, packet) == 0) {
+ MTPD("MTP_RESPONSE_OK\n");
+ return MTP_RESPONSE_OK;
+ }
+ }
+ MTPE("MyMtpDatabase::getObjectPropertyList MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ if (storit->second->getObjectInfo(handle, info) == 0) {
+ MTPD("MTP_RESPONSE_OK\n");
+ return MTP_RESPONSE_OK;
+ }
+ }
+ MTPE("MyMtpDatabase::getObjectInfo MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+}
+
+void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
+ MtpString path;
+ int64_t length;
+ MtpObjectFormat format;
+ void* result = NULL;
+ outThumbSize = 0;
+ MTPE("MyMtpDatabase::getThumbnail not implemented, returning 0\n");
+ return 0;
+}
+
+MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ MTPD("MyMtpDatabase::getObjectFilePath calling getObhectFilePath\n");
+ if (storit->second->getObjectFilePath(handle, outFilePath, outFileLength, outFormat) == 0) {
+ MTPD("MTP_RESPONSE_OK\n");
+ return MTP_RESPONSE_OK;
+ }
+ }
+ MTPE("MyMtpDatabase::getObjectFilePath MTP_RESPOSNE_INVALID_OBJECT_HANDLE %i\n", handle);
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+}
+
+MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
+ MTPD("deleteFile\n");
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ if (storit->second->deleteFile(handle) == 0) {
+ MTPD("MTP_RESPONSE_OK\n");
+ return MTP_RESPONSE_OK;
+ }
+ }
+ MTPE("MyMtpDatabase::deleteFile MTP_RESPONSE_INVALID_OBJECT_HANDLE %i\n", handle);
+ return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
+}
+
+struct PropertyTableEntry {
+ MtpObjectProperty property;
+ int type;
+};
+
+static const PropertyTableEntry kObjectPropertyTable[] = {
+ { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
+ { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
+ { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
+ { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
+ { MTP_PROPERTY_NAME, MTP_TYPE_STR },
+ { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
+ { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
+ { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
+ { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
+ { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
+ { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
+ { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
+ { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
+ { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
+ { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
+ { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
+};
+
+static const PropertyTableEntry kDevicePropertyTable[] = {
+ { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
+ { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
+ { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
+};
+
+bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
+ int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
+ const PropertyTableEntry* entry = kObjectPropertyTable;
+ MTPD("MyMtpDatabase::getObjectPropertyInfo size is: %i\n", count);
+ for (int i = 0; i < count; i++, entry++) {
+ if (entry->property == property) {
+ type = entry->type;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
+ int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
+ const PropertyTableEntry* entry = kDevicePropertyTable;
+ MTPD("MyMtpDatabase::getDevicePropertyInfo count is: %i\n", count);
+ for (int i = 0; i < count; i++, entry++) {
+ if (entry->property == property) {
+ type = entry->type;
+ MTPD("type: %x\n", type);
+ return true;
+ }
+ }
+ return false;
+}
+
+MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
+ // call function and place files with associated handles into int array
+ MTPD("MyMtpDatabase::getObjectReferences returning null, this seems to be what Android always does.\n");
+ MTPD("handle: %d\n", handle);
+ // Windows + Android seems to always return a NULL in this function, c == null path
+ // The way that this is handled in Android then is to do this:
+ return NULL;
+}
+
+MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
+ MtpObjectHandleList* references) {
+ int count = references->size();
+ MTPE("MyMtpDatabase::setObjectReferences not implemented, returning 0\n");
+ return 0;
+}
+
+MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
+ MtpObjectFormat format) {
+ MTPD("MyMtpDatabase::getObjectPropertyDesc start\n");
+ MtpProperty* result = NULL;
+ switch (property) {
+ case MTP_PROPERTY_OBJECT_FORMAT:
+ // use format as default value
+ MTPD("MyMtpDatabase::getObjectPropertyDesc format\n");
+ result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
+ break;
+ case MTP_PROPERTY_PROTECTION_STATUS:
+ case MTP_PROPERTY_TRACK:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc track\n");
+ result = new MtpProperty(property, MTP_TYPE_UINT16);
+ break;
+ case MTP_PROPERTY_STORAGE_ID:
+ case MTP_PROPERTY_PARENT_OBJECT:
+ case MTP_PROPERTY_DURATION:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc duration\n");
+ result = new MtpProperty(property, MTP_TYPE_UINT32);
+ break;
+ case MTP_PROPERTY_OBJECT_SIZE:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc size\n");
+ result = new MtpProperty(property, MTP_TYPE_UINT64);
+ break;
+ case MTP_PROPERTY_PERSISTENT_UID:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc persistent uid\n");
+ result = new MtpProperty(property, MTP_TYPE_UINT128);
+ break;
+ case MTP_PROPERTY_NAME:
+ case MTP_PROPERTY_DISPLAY_NAME:
+ case MTP_PROPERTY_ARTIST:
+ case MTP_PROPERTY_ALBUM_NAME:
+ case MTP_PROPERTY_ALBUM_ARTIST:
+ case MTP_PROPERTY_GENRE:
+ case MTP_PROPERTY_COMPOSER:
+ case MTP_PROPERTY_DESCRIPTION:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc description\n");
+ result = new MtpProperty(property, MTP_TYPE_STR);
+ break;
+ case MTP_PROPERTY_DATE_MODIFIED:
+ case MTP_PROPERTY_DATE_ADDED:
+ case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc date\n");
+ result = new MtpProperty(property, MTP_TYPE_STR);
+ result->setFormDateTime();
+ break;
+ case MTP_PROPERTY_OBJECT_FILE_NAME:
+ MTPD("MyMtpDatabase::getObjectPropertyDesc file name\n");
+ // We allow renaming files and folders
+ result = new MtpProperty(property, MTP_TYPE_STR, true);
+ break;
+ }
+ return result;
+}
+
+MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
+ MtpProperty* result = NULL;
+ int ret;
+ bool writable = true;
+ switch (property) {
+ case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
+ case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
+ ret = MTP_RESPONSE_OK;
+ // fall through
+ case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
+ result = new MtpProperty(property, MTP_TYPE_STR, writable);
+ ret = MTP_RESPONSE_OK;
+
+ // get current value
+ if (ret == MTP_RESPONSE_OK) {
+ MTPD("here\n");
+ result->setCurrentValue('\0');
+ result->setDefaultValue('\0');
+ } else {
+ MTPE("unable to read device property, response: %04X", ret);
+ }
+ break;
+ default:
+ ret = MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
+ break;
+ }
+
+ return result;
+}
+
+void MyMtpDatabase::sessionStarted() {
+ MTPD("MyMtpDatabase::sessionStarted not implemented or does nothing, returning\n");
+ return;
+}
+
+void MyMtpDatabase::sessionEnded() {
+ MTPD("MyMtpDatabase::sessionEnded not implemented or does nothing, returning\n");
+ return;
+}
+
+// ----------------------------------------------------------------------------
+
+static void
+android_mtp_MtpDatabase_setup()
+{
+ MyMtpDatabase* database = new MyMtpDatabase();
+}
+
+static void
+android_mtp_MtpDatabase_finalize()
+{
+ return;
+}
+
+static std::string
+android_mtp_MtpPropertyGroup_format_date_time(long seconds)
+{
+ char date[20];
+ formatDateTime(seconds, date, sizeof(date));
+ return date;
+}
+
+void MyMtpDatabase::lockMutex(void) {
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ storit->second->lockMutex(0);
+ }
+}
+
+void MyMtpDatabase::unlockMutex(void) {
+ std::map<int, MtpStorage*>::iterator storit;
+ for (storit = storagemap.begin(); storit != storagemap.end(); storit++) {
+ storit->second->unlockMutex(0);
+ }
+}