From c7eee6fef0263ed4eb5aa0d934a0a8c972d41b30 Mon Sep 17 00:00:00 2001 From: bigbiff bigbiff Date: Tue, 2 Sep 2014 18:59:01 -0400 Subject: add mtp responder to TWRP. Big thanks to Dees_Troy for helping with the implementation. Change-Id: I6c9c522b9c9de5dc139e2ecb0141008182ba07f0 --- mtp/mtp_MtpDatabase.cpp | 884 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 884 insertions(+) create mode 100755 mtp/mtp_MtpDatabase.cpp (limited to 'mtp/mtp_MtpDatabase.cpp') 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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::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::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::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::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::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::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::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::iterator storit; + for (storit = storagemap.begin(); storit != storagemap.end(); storit++) { + storit->second->lockMutex(0); + } +} + +void MyMtpDatabase::unlockMutex(void) { + std::map::iterator storit; + for (storit = storagemap.begin(); storit != storagemap.end(); storit++) { + storit->second->unlockMutex(0); + } +} -- cgit v1.2.3