add mtp responder to TWRP.

Big thanks to Dees_Troy for helping with the implementation.

Change-Id: I6c9c522b9c9de5dc139e2ecb0141008182ba07f0
This commit is contained in:
bigbiff bigbiff
2014-09-02 18:59:01 -04:00
parent 3c4ac3bc32
commit c7eee6fef0
59 changed files with 9663 additions and 28 deletions
+9 -4
View File
@@ -73,7 +73,8 @@ LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_STATIC_LIBRARIES += libcrecovery libguitwrp
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libtar libblkid libminuitwrp libminadbd libmtdutils libminzip libaosprecovery
LOCAL_SHARED_LIBRARIES += libz libc libstlport libcutils libstdc++ libtar libblkid libminuitwrp libminadbd libmtdutils libminzip libaosprecovery libcorkscrew
LOCAL_SHARED_LIBRARIES += libgccdemangle
ifneq ($(wildcard system/core/libsparse/Android.mk),)
LOCAL_SHARED_LIBRARIES += libsparse
@@ -84,6 +85,7 @@ ifeq ($(TW_OEM_BUILD),true)
BOARD_HAS_NO_REAL_SDCARD := true
TW_USE_TOOLBOX := true
TW_EXCLUDE_SUPERSU := true
TW_EXCLUDE_MTP := true
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
LOCAL_CFLAGS += -DUSE_EXT4
@@ -124,6 +126,10 @@ LOCAL_MODULE_TAGS := eng
LOCAL_C_INCLUDES += system/extras/ext4_utils
#TWRP Build Flags
ifeq ($(TW_EXCLUDE_MTP),)
LOCAL_SHARED_LIBRARIES += libtwrpmtp
LOCAL_CFLAGS += -DTW_HAS_MTP
endif
ifneq ($(TW_NO_SCREEN_TIMEOUT),)
LOCAL_CFLAGS += -DTW_NO_SCREEN_TIMEOUT
endif
@@ -373,7 +379,8 @@ include $(commands_recovery_local_path)/injecttwrp/Android.mk \
$(commands_recovery_local_path)/openaes/Android.mk \
$(commands_recovery_local_path)/toolbox/Android.mk \
$(commands_recovery_local_path)/libmincrypt/Android.mk \
$(commands_recovery_local_path)/twrpTarMain/Android.mk
$(commands_recovery_local_path)/twrpTarMain/Android.mk \
$(commands_recovery_local_path)/mtp/Android.mk
ifeq ($(TW_INCLUDE_CRYPTO_SAMSUNG), true)
include $(commands_recovery_local_path)/crypto/libcrypt_samsung/Android.mk
@@ -411,5 +418,3 @@ endif
ifeq ($(TW_INCLUDE_FB2PNG), true)
include $(commands_recovery_local_path)/fb2png/Android.mk
endif
commands_recovery_local_path :=
+8
View File
@@ -996,6 +996,14 @@ void DataManager::SetDefaultValues()
LOGINFO("TW_EXCLUDE_ENCRYPTED_BACKUPS := true\n");
mValues.insert(make_pair("tw_include_encrypted_backup", make_pair("0", 0)));
#endif
#ifdef TW_HAS_MTP
mConstValues.insert(make_pair("tw_has_mtp", "1"));
mValues.insert(make_pair("tw_mtp_enabled", make_pair("1", 1)));
#else
LOGINFO("TW_EXCLUDE_MTP := true\n");
mConstValues.insert(make_pair("tw_has_mtp", "0"));
mConstValues.insert(make_pair("tw_mtp_enabled", "0"));
#endif
}
// Magic Values
+21 -2
View File
@@ -23,7 +23,7 @@ on init
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/idVendor 18D1
write /sys/class/android_usb/android0/idProduct D001
write /sys/class/android_usb/android0/idProduct D002
write /sys/class/android_usb/android0/functions adb
write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
write /sys/class/android_usb/android0/iProduct ${ro.product.model}
@@ -51,6 +51,25 @@ on property:sys.storage.ums_enabled=0
write /sys/class/android_usb/android0/functions adb
write /sys/class/android_usb/android0/enable ${service.adb.root}
on property:sys.usb.config=none
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/bDeviceClass 0
on property:sys.usb.config=mtp,adb
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/functions mtp,adb
write /sys/class/android_usb/android0/enable 1
start adbd
on property:sys.usb.config=adb
stop adbd
write /sys/class/android_usb/android0/enable 0
write /sys/class/android_usb/android0/functions adb
write /sys/class/android_usb/android0/enable ${service.adb.root}
start adbd
service ueventd /sbin/ueventd
critical
@@ -73,4 +92,4 @@ on property:ro.debuggable=1
on property:service.adb.root=1
write /sys/class/android_usb/android0/enable 0
restart adbd
write /sys/class/android_usb/android0/enable 1
write /sys/class/android_usb/android0/enable 1
+1 -1
View File
@@ -62,7 +62,7 @@ endif
ifeq ($(HAVE_SELINUX), true)
LOCAL_CFLAGS += -DHAVE_SELINUX
endif
ifeq ($(TW_OEM_BUILD),true)
ifeq ($(TW_OEM_BUILD), true)
LOCAL_CFLAGS += -DTW_OEM_BUILD
endif
+26 -1
View File
@@ -1305,7 +1305,6 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
} else {
ret = 1; // failure
}
PartitionManager.Update_System_Details();
if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
operation_start("ReinjectTWRP");
gui_print("Injecting TWRP into boot image...\n");
@@ -1469,6 +1468,32 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
operation_end(op_status, simulate);
return 0;
}
if (function == "startmtp")
{
int op_status = 0;
operation_start("Start MTP");
if (PartitionManager.Enable_MTP())
op_status = 0; // success
else
op_status = 1; // fail
operation_end(op_status, simulate);
return 0;
}
if (function == "stopmtp")
{
int op_status = 0;
operation_start("Stop MTP");
if (PartitionManager.Disable_MTP())
op_status = 0; // success
else
op_status = 1; // fail
operation_end(op_status, simulate);
return 0;
}
}
else
{
+39
View File
@@ -901,6 +901,45 @@
<action function="page">usb_mount</action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="0" />
</conditions>
<placement x="%col3_x%" y="row1_y" />
<font resource="font" color="%button_text_color%" />
<text>Enable MTP</text>
<image resource="main_button" />
<action function="startmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="1" />
</conditions>
<placement x="%col3_x%" y="row1_y" />
<font resource="font" color="%button_text_color%" />
<text>Disable MTP</text>
<image resource="main_button" />
<action function="stopmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_is_encrypted" var2="1" />
<condition var1="tw_is_decrypted" var2="0" />
</conditions>
<placement x="%col3_x%" y="row1_y" />
<font resource="font" color="%button_text_color%" />
<text>Decrypt Data</text>
<image resource="main_button" />
<action function="page">decrypt</action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<fill color="%button_fill_color%" />
+28
View File
@@ -2143,6 +2143,32 @@
<action function="page">usb_mount</action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="0" />
</conditions>
<placement x="%col2_x%" y="row4_y" />
<font resource="font" color="%button_text_color%" />
<text>Enable MTP</text>
<image resource="main_button" />
<action function="startmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="1" />
</conditions>
<placement x="%col2_x%" y="row4_y" />
<font resource="font" color="%button_text_color%" />
<text>Disable MTP</text>
<image resource="main_button" />
<action function="stopmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
@@ -2201,6 +2227,7 @@
<object type="action">
<action function="mount">usb</action>
<action function="set">tw_busy=1</action>
</object>
<object type="template" name="footer" />
@@ -2213,6 +2240,7 @@
<object type="action">
<action function="page">mount</action>
<action function="set">tw_busy=0</action>
</object>
</page>
+26
View File
@@ -2115,6 +2115,32 @@
<action function="page">usb_mount</action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="0" />
</conditions>
<placement x="%col2_x%" y="row4_y" />
<font resource="font" color="%button_text_color%" />
<text>Enable MTP</text>
<image resource="main_button" />
<action function="startmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
<condition var1="tw_has_mtp" var2="1" />
<condition var1="tw_mtp_enabled" var2="1" />
</conditions>
<placement x="%col2_x%" y="row4_y" />
<font resource="font" color="%button_text_color%" />
<text>Disable MTP</text>
<image resource="main_button" />
<action function="stopmtp"></action>
</object>
<object type="button">
<highlight color="%highlight_color%" />
<conditions>
Executable
+65
View File
@@ -0,0 +1,65 @@
LOCAL_PATH := $(call my-dir)
# Build libtwrpmtp library
include $(CLEAR_VARS)
LOCAL_MODULE := libtwrpmtp
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -DMTP_DEVICE -DMTP_HOST
LOCAL_C_INCLUDES += $(LOCAL_PATH) bionic external/stlport/stlport frameworks/base/include system/core/include bionic/libc/private/
LOCAL_SRC_FILES = \
btree.cpp \
MtpDataPacket.cpp \
MtpDebug.cpp \
MtpDevice.cpp \
MtpDeviceInfo.cpp \
MtpEventPacket.cpp \
MtpObjectInfo.cpp \
MtpPacket.cpp \
MtpProperty.cpp \
MtpRequestPacket.cpp \
MtpResponsePacket.cpp \
MtpServer.cpp \
MtpStorage.cpp \
MtpStorageInfo.cpp \
MtpStringBuffer.cpp \
MtpUtils.cpp \
mtp_MtpServer.cpp \
twrpMtp.cpp \
mtp_MtpDatabase.cpp \
node.cpp
LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils
include $(BUILD_SHARED_LIBRARY)
# Build twrpmtp binary / executable
include $(CLEAR_VARS)
LOCAL_MODULE := twrpmtp
LOCAL_MODULE_TAGS := optional
LOCAL_CFLAGS = -D_FILE_OFFSET_BITS=64 -DMTP_DEVICE -DMTP_HOST -DTWRPMTP
LOCAL_C_INCLUDES += $(LOCAL_PATH) bionic external/stlport/stlport frameworks/base/include system/core/include bionic/libc/private/
LOCAL_SRC_FILES = \
btree.cpp \
MtpDataPacket.cpp \
MtpDebug.cpp \
MtpDevice.cpp \
MtpDeviceInfo.cpp \
MtpEventPacket.cpp \
MtpObjectInfo.cpp \
MtpPacket.cpp \
MtpProperty.cpp \
MtpRequestPacket.cpp \
MtpResponsePacket.cpp \
MtpServer.cpp \
MtpStorage.cpp \
MtpStorageInfo.cpp \
MtpStringBuffer.cpp \
MtpUtils.cpp \
mtp_MtpServer.cpp \
twrpMtp.cpp \
mtp_MtpDatabase.cpp \
node.cpp
LOCAL_SHARED_LIBRARIES += libz libc libusbhost libstdc++ libstlport libdl libcutils libutils
include $(BUILD_EXECUTABLE)
+488
View File
@@ -0,0 +1,488 @@
/*
* 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 <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <usbhost/usbhost.h>
#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
#include "MtpDebug.h"
#define MTP_BUFFER_SIZE 16384
MtpDataPacket::MtpDataPacket()
: MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE
mOffset(MTP_CONTAINER_HEADER_SIZE)
{
}
MtpDataPacket::~MtpDataPacket() {
}
void MtpDataPacket::reset() {
MtpPacket::reset();
mOffset = MTP_CONTAINER_HEADER_SIZE;
}
void MtpDataPacket::setOperationCode(MtpOperationCode code) {
MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
}
void MtpDataPacket::setTransactionID(MtpTransactionID id) {
MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
}
uint16_t MtpDataPacket::getUInt16() {
int offset = mOffset;
uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
mOffset += 2;
return result;
}
uint32_t MtpDataPacket::getUInt32() {
int offset = mOffset;
uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);
mOffset += 4;
return result;
}
uint64_t MtpDataPacket::getUInt64() {
int offset = mOffset;
uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);
mOffset += 8;
return result;
}
void MtpDataPacket::getUInt128(uint128_t& value) {
value[0] = getUInt32();
value[1] = getUInt32();
value[2] = getUInt32();
value[3] = getUInt32();
}
void MtpDataPacket::getString(MtpStringBuffer& string)
{
string.readFromPacket(this);
}
Int8List* MtpDataPacket::getAInt8() {
Int8List* result = new Int8List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getInt8());
return result;
}
UInt8List* MtpDataPacket::getAUInt8() {
UInt8List* result = new UInt8List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getUInt8());
return result;
}
Int16List* MtpDataPacket::getAInt16() {
Int16List* result = new Int16List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getInt16());
return result;
}
UInt16List* MtpDataPacket::getAUInt16() {
UInt16List* result = new UInt16List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getUInt16());
return result;
}
Int32List* MtpDataPacket::getAInt32() {
Int32List* result = new Int32List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getInt32());
return result;
}
UInt32List* MtpDataPacket::getAUInt32() {
UInt32List* result = new UInt32List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getUInt32());
return result;
}
Int64List* MtpDataPacket::getAInt64() {
Int64List* result = new Int64List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getInt64());
return result;
}
UInt64List* MtpDataPacket::getAUInt64() {
UInt64List* result = new UInt64List;
int count = getUInt32();
for (int i = 0; i < count; i++)
result->push(getUInt64());
return result;
}
void MtpDataPacket::putInt8(int8_t value) {
allocate(mOffset + 1);
mBuffer[mOffset++] = (uint8_t)value;
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putUInt8(uint8_t value) {
allocate(mOffset + 1);
mBuffer[mOffset++] = (uint8_t)value;
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putInt16(int16_t value) {
allocate(mOffset + 2);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putUInt16(uint16_t value) {
allocate(mOffset + 2);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putInt32(int32_t value) {
allocate(mOffset + 4);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putUInt32(uint32_t value) {
allocate(mOffset + 4);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putInt64(int64_t value) {
allocate(mOffset + 8);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putUInt64(uint64_t value) {
allocate(mOffset + 8);
mBuffer[mOffset++] = (uint8_t)(value & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF);
mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF);
if (mPacketSize < mOffset)
mPacketSize = mOffset;
}
void MtpDataPacket::putInt128(const int128_t& value) {
putInt32(value[0]);
putInt32(value[1]);
putInt32(value[2]);
putInt32(value[3]);
}
void MtpDataPacket::putUInt128(const uint128_t& value) {
putUInt32(value[0]);
putUInt32(value[1]);
putUInt32(value[2]);
putUInt32(value[3]);
}
void MtpDataPacket::putInt128(int64_t value) {
putInt64(value);
putInt64(value < 0 ? -1 : 0);
}
void MtpDataPacket::putUInt128(uint64_t value) {
putUInt64(value);
putUInt64(0);
}
void MtpDataPacket::putAInt8(const int8_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putInt8(*values++);
}
void MtpDataPacket::putAUInt8(const uint8_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putUInt8(*values++);
}
void MtpDataPacket::putAInt16(const int16_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putInt16(*values++);
}
void MtpDataPacket::putAUInt16(const uint16_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putUInt16(*values++);
}
void MtpDataPacket::putAUInt16(const UInt16List* values) {
size_t count = (values ? values->size() : 0);
putUInt32(count);
for (size_t i = 0; i < count; i++)
putUInt16((*values)[i]);
}
void MtpDataPacket::putAInt32(const int32_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putInt32(*values++);
}
void MtpDataPacket::putAUInt32(const uint32_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putUInt32(*values++);
}
void MtpDataPacket::putAUInt32(const UInt32List* list) {
if (!list) {
putEmptyArray();
} else {
size_t size = list->size();
putUInt32(size);
for (size_t i = 0; i < size; i++)
putUInt32((*list)[i]);
}
}
void MtpDataPacket::putAInt64(const int64_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putInt64(*values++);
}
void MtpDataPacket::putAUInt64(const uint64_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)
putUInt64(*values++);
}
void MtpDataPacket::putString(const MtpStringBuffer& string) {
string.writeToPacket(this);
}
void MtpDataPacket::putString(const char* s) {
MtpStringBuffer string(s);
string.writeToPacket(this);
}
void MtpDataPacket::putString(const uint16_t* string) {
int count = 0;
for (int i = 0; i < 256; i++) {
if (string[i])
count++;
else
break;
}
putUInt8(count > 0 ? count + 1 : 0);
for (int i = 0; i < count; i++)
putUInt16(string[i]);
// only terminate with zero if string is not empty
if (count > 0)
putUInt16(0);
}
#ifdef MTP_DEVICE
int MtpDataPacket::read(int fd) {
int ret = ::read(fd, mBuffer, MTP_BUFFER_SIZE);
if (ret < MTP_CONTAINER_HEADER_SIZE)
return -1;
mPacketSize = ret;
mOffset = MTP_CONTAINER_HEADER_SIZE;
return ret;
}
int MtpDataPacket::write(int fd) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
int ret = ::write(fd, mBuffer, mPacketSize);
return (ret < 0 ? ret : 0);
}
int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
allocate(length);
memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);
length += MTP_CONTAINER_HEADER_SIZE;
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
int ret = ::write(fd, mBuffer, length);
return (ret < 0 ? ret : 0);
}
#endif // MTP_DEVICE
#ifdef MTP_HOST
int MtpDataPacket::read(struct usb_request *request) {
// first read the header
request->buffer = mBuffer;
request->buffer_length = mBufferSize;
int32_t length = transfer(request);
if (length >= MTP_CONTAINER_HEADER_SIZE) {
// look at the length field to see if the data spans multiple packets
uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
allocate(totalLength);
while (totalLength > (uint32_t)length) {
request->buffer = mBuffer + length;
request->buffer_length = totalLength - length;
int ret = transfer(request);
if (ret >= 0)
length += ret;
else {
length = ret;
break;
}
}
}
if (length >= 0)
mPacketSize = length;
return length;
}
int MtpDataPacket::readData(struct usb_request *request, void* buffer, int length) {
int read = 0;
while (read < length) {
request->buffer = (char *)buffer + read;
request->buffer_length = length - read;
int ret = transfer(request);
if (ret < 0) {
return ret;
}
read += ret;
}
return read;
}
// Queue a read request. Call readDataWait to wait for result
int MtpDataPacket::readDataAsync(struct usb_request *req) {
if (usb_request_queue(req)) {
MTPE("usb_endpoint_queue failed, errno: %d", errno);
return -1;
}
return 0;
}
// Wait for result of readDataAsync
int MtpDataPacket::readDataWait(struct usb_device *device) {
struct usb_request *req = usb_request_wait(device);
return (req ? req->actual_length : -1);
}
int MtpDataPacket::readDataHeader(struct usb_request *request) {
request->buffer = mBuffer;
request->buffer_length = request->max_packet_size;
int length = transfer(request);
if (length >= 0)
mPacketSize = length;
return length;
}
int MtpDataPacket::writeDataHeader(struct usb_request *request, uint32_t length) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
request->buffer = mBuffer;
request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
int ret = transfer(request);
return (ret < 0 ? ret : 0);
}
int MtpDataPacket::write(struct usb_request *request) {
MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA);
// send header separately from data
request->buffer = mBuffer;
request->buffer_length = MTP_CONTAINER_HEADER_SIZE;
int ret = transfer(request);
if (ret == MTP_CONTAINER_HEADER_SIZE) {
request->buffer = mBuffer + MTP_CONTAINER_HEADER_SIZE;
request->buffer_length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
ret = transfer(request);
}
return (ret < 0 ? ret : 0);
}
int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t length) {
request->buffer = buffer;
request->buffer_length = length;
int ret = transfer(request);
return (ret < 0 ? ret : 0);
}
#endif // MTP_HOST
void* MtpDataPacket::getData(int& outLength) const {
int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
if (length > 0) {
void* result = malloc(length);
if (result) {
memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
outLength = length;
return result;
}
}
outLength = 0;
return NULL;
}
+123
View File
@@ -0,0 +1,123 @@
/*
* 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++
*
*/
#ifndef _MTP_DATA_PACKET_H
#define _MTP_DATA_PACKET_H
#include "MtpPacket.h"
#include "mtp.h"
struct usb_device;
struct usb_request;
class MtpStringBuffer;
class MtpDataPacket : public MtpPacket {
private:
// current offset for get/put methods
uint64_t mOffset;
public:
MtpDataPacket();
virtual ~MtpDataPacket();
virtual void reset();
void setOperationCode(MtpOperationCode code);
void setTransactionID(MtpTransactionID id);
inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; }
inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; }
uint16_t getUInt16();
inline int16_t getInt16() { return (int16_t)getUInt16(); }
uint32_t getUInt32();
inline int32_t getInt32() { return (int32_t)getUInt32(); }
uint64_t getUInt64();
inline int64_t getInt64() { return (int64_t)getUInt64(); }
void getUInt128(uint128_t& value);
inline void getInt128(int128_t& value) { getUInt128((uint128_t&)value); }
void getString(MtpStringBuffer& string);
Int8List* getAInt8();
UInt8List* getAUInt8();
Int16List* getAInt16();
UInt16List* getAUInt16();
Int32List* getAInt32();
UInt32List* getAUInt32();
Int64List* getAInt64();
UInt64List* getAUInt64();
void putInt8(int8_t value);
void putUInt8(uint8_t value);
void putInt16(int16_t value);
void putUInt16(uint16_t value);
void putInt32(int32_t value);
void putUInt32(uint32_t value);
void putInt64(int64_t value);
void putUInt64(uint64_t value);
void putInt128(const int128_t& value);
void putUInt128(const uint128_t& value);
void putInt128(int64_t value);
void putUInt128(uint64_t value);
void putAInt8(const int8_t* values, int count);
void putAUInt8(const uint8_t* values, int count);
void putAInt16(const int16_t* values, int count);
void putAUInt16(const uint16_t* values, int count);
void putAUInt16(const UInt16List* values);
void putAInt32(const int32_t* values, int count);
void putAUInt32(const uint32_t* values, int count);
void putAUInt32(const UInt32List* list);
void putAInt64(const int64_t* values, int count);
void putAUInt64(const uint64_t* values, int count);
void putString(const MtpStringBuffer& string);
void putString(const char* string);
void putString(const uint16_t* string);
inline void putEmptyString() { putUInt8(0); }
inline void putEmptyArray() { putUInt32(0); }
#ifdef MTP_DEVICE
// fill our buffer with data from the given file descriptor
int read(int fd);
// write our data to the given file descriptor
int write(int fd);
int writeData(int fd, void* data, uint32_t length);
#endif
#ifdef MTP_HOST
int read(struct usb_request *request);
int readData(struct usb_request *request, void* buffer, int length);
int readDataAsync(struct usb_request *req);
int readDataWait(struct usb_device *device);
int readDataHeader(struct usb_request *ep);
int writeDataHeader(struct usb_request *ep, uint32_t length);
int write(struct usb_request *ep);
int write(struct usb_request *ep, void* buffer, uint32_t length);
#endif
inline bool hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
inline uint32_t getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
void* getData(int& outLength) const;
};
#endif // _MTP_DATA_PACKET_H
+115
View File
@@ -0,0 +1,115 @@
/*
* 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++
*/
#ifndef _MTP_DATABASE_H
#define _MTP_DATABASE_H
#include "MtpTypes.h"
class MtpDataPacket;
class MtpProperty;
class MtpObjectInfo;
class MtpDatabase {
public:
virtual ~MtpDatabase() {}
// called from SendObjectInfo to reserve a database entry for the incoming file
virtual MtpObjectHandle beginSendObject(const char* path,
MtpObjectFormat format,
MtpObjectHandle parent,
MtpStorageID storage,
uint64_t size,
time_t modified) = 0;
// called to report success or failure of the SendObject file transfer
// success should signal a notification of the new object's creation,
// failure should remove the database entry created in beginSendObject
virtual void endSendObject(const char* path,
MtpObjectHandle handle,
MtpObjectFormat format,
bool succeeded) = 0;
virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent) = 0;
virtual int getNumObjects(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent) = 0;
// callee should delete[] the results from these
// results can be NULL
virtual MtpObjectFormatList* getSupportedPlaybackFormats() = 0;
virtual MtpObjectFormatList* getSupportedCaptureFormats() = 0;
virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format) = 0;
virtual MtpDevicePropertyList* getSupportedDeviceProperties() = 0;
virtual void createDB(MtpStorage* storage, MtpStorageID storageID) = 0;
virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) = 0;
virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet) = 0;
virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
MtpDataPacket& packet) = 0;
virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
MtpDataPacket& packet) = 0;
virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property) = 0;
virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
uint32_t format, uint32_t property,
int groupCode, int depth,
MtpDataPacket& packet) = 0;
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info) = 0;
virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) = 0;
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath,
int64_t& outFileLength,
MtpObjectFormat& outFormat) = 0;
virtual MtpResponseCode deleteFile(MtpObjectHandle handle) = 0;
virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle) = 0;
virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
MtpObjectHandleList* references) = 0;
virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
MtpObjectFormat format) = 0;
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property) = 0;
virtual void sessionStarted() = 0;
virtual void sessionEnded() = 0;
virtual void lockMutex() = 0;
virtual void unlockMutex() = 0;
};
#endif // _MTP_DATABASE_H
+419
View File
@@ -0,0 +1,419 @@
/*
* 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 "MtpDebug.h"
#include <stdarg.h>
#include <stdio.h>
#define MTP_DEBUG_BUFFER_SIZE 2048
//#define MTP_DEBUG 1
extern "C" void mtpdebug(const char *fmt, ...)
{
#ifdef MTP_DEBUG
char buf[MTP_DEBUG_BUFFER_SIZE]; // We're going to limit a single request to 512 bytes
va_list ap;
va_start(ap, fmt);
vsnprintf(buf, MTP_DEBUG_BUFFER_SIZE, fmt, ap);
va_end(ap);
fputs(buf, stdout);
#endif
}
struct CodeEntry {
const char* name;
uint16_t code;
};
static const CodeEntry sOperationCodes[] = {
{ "MTP_OPERATION_GET_DEVICE_INFO", 0x1001 },
{ "MTP_OPERATION_OPEN_SESSION", 0x1002 },
{ "MTP_OPERATION_CLOSE_SESSION", 0x1003 },
{ "MTP_OPERATION_GET_STORAGE_IDS", 0x1004 },
{ "MTP_OPERATION_GET_STORAGE_INFO", 0x1005 },
{ "MTP_OPERATION_GET_NUM_OBJECTS", 0x1006 },
{ "MTP_OPERATION_GET_OBJECT_HANDLES", 0x1007 },
{ "MTP_OPERATION_GET_OBJECT_INFO", 0x1008 },
{ "MTP_OPERATION_GET_OBJECT", 0x1009 },
{ "MTP_OPERATION_GET_THUMB", 0x100A },
{ "MTP_OPERATION_DELETE_OBJECT", 0x100B },
{ "MTP_OPERATION_SEND_OBJECT_INFO", 0x100C },
{ "MTP_OPERATION_SEND_OBJECT", 0x100D },
{ "MTP_OPERATION_INITIATE_CAPTURE", 0x100E },
{ "MTP_OPERATION_FORMAT_STORE", 0x100F },
{ "MTP_OPERATION_RESET_DEVICE", 0x1010 },
{ "MTP_OPERATION_SELF_TEST", 0x1011 },
{ "MTP_OPERATION_SET_OBJECT_PROTECTION", 0x1012 },
{ "MTP_OPERATION_POWER_DOWN", 0x1013 },
{ "MTP_OPERATION_GET_DEVICE_PROP_DESC", 0x1014 },
{ "MTP_OPERATION_GET_DEVICE_PROP_VALUE", 0x1015 },
{ "MTP_OPERATION_SET_DEVICE_PROP_VALUE", 0x1016 },
{ "MTP_OPERATION_RESET_DEVICE_PROP_VALUE", 0x1017 },
{ "MTP_OPERATION_TERMINATE_OPEN_CAPTURE", 0x1018 },
{ "MTP_OPERATION_MOVE_OBJECT", 0x1019 },
{ "MTP_OPERATION_COPY_OBJECT", 0x101A },
{ "MTP_OPERATION_GET_PARTIAL_OBJECT", 0x101B },
{ "MTP_OPERATION_INITIATE_OPEN_CAPTURE", 0x101C },
{ "MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED", 0x9801 },
{ "MTP_OPERATION_GET_OBJECT_PROP_DESC", 0x9802 },
{ "MTP_OPERATION_GET_OBJECT_PROP_VALUE", 0x9803 },
{ "MTP_OPERATION_SET_OBJECT_PROP_VALUE", 0x9804 },
{ "MTP_OPERATION_GET_OBJECT_PROP_LIST", 0x9805 },
{ "MTP_OPERATION_SET_OBJECT_PROP_LIST", 0x9806 },
{ "MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC", 0x9807 },
{ "MTP_OPERATION_SEND_OBJECT_PROP_LIST", 0x9808 },
{ "MTP_OPERATION_GET_OBJECT_REFERENCES", 0x9810 },
{ "MTP_OPERATION_SET_OBJECT_REFERENCES", 0x9811 },
{ "MTP_OPERATION_SKIP", 0x9820 },
// android extensions
{ "MTP_OPERATION_GET_PARTIAL_OBJECT_64", 0x95C1 },
{ "MTP_OPERATION_SEND_PARTIAL_OBJECT", 0x95C2 },
{ "MTP_OPERATION_TRUNCATE_OBJECT", 0x95C3 },
{ "MTP_OPERATION_BEGIN_EDIT_OBJECT", 0x95C4 },
{ "MTP_OPERATION_END_EDIT_OBJECT", 0x95C5 },
{ 0, 0 },
};
static const CodeEntry sFormatCodes[] = {
{ "MTP_FORMAT_UNDEFINED", 0x3000 },
{ "MTP_FORMAT_ASSOCIATION", 0x3001 },
{ "MTP_FORMAT_SCRIPT", 0x3002 },
{ "MTP_FORMAT_EXECUTABLE", 0x3003 },
{ "MTP_FORMAT_TEXT", 0x3004 },
{ "MTP_FORMAT_HTML", 0x3005 },
{ "MTP_FORMAT_DPOF", 0x3006 },
{ "MTP_FORMAT_AIFF", 0x3007 },
{ "MTP_FORMAT_WAV", 0x3008 },
{ "MTP_FORMAT_MP3", 0x3009 },
{ "MTP_FORMAT_AVI", 0x300A },
{ "MTP_FORMAT_MPEG", 0x300B },
{ "MTP_FORMAT_ASF", 0x300C },
{ "MTP_FORMAT_DEFINED", 0x3800 },
{ "MTP_FORMAT_EXIF_JPEG", 0x3801 },
{ "MTP_FORMAT_TIFF_EP", 0x3802 },
{ "MTP_FORMAT_FLASHPIX", 0x3803 },
{ "MTP_FORMAT_BMP", 0x3804 },
{ "MTP_FORMAT_CIFF", 0x3805 },
{ "MTP_FORMAT_GIF", 0x3807 },
{ "MTP_FORMAT_JFIF", 0x3808 },
{ "MTP_FORMAT_CD", 0x3809 },
{ "MTP_FORMAT_PICT", 0x380A },
{ "MTP_FORMAT_PNG", 0x380B },
{ "MTP_FORMAT_TIFF", 0x380D },
{ "MTP_FORMAT_TIFF_IT", 0x380E },
{ "MTP_FORMAT_JP2", 0x380F },
{ "MTP_FORMAT_JPX", 0x3810 },
{ "MTP_FORMAT_UNDEFINED_FIRMWARE", 0xB802 },
{ "MTP_FORMAT_WINDOWS_IMAGE_FORMAT", 0xB881 },
{ "MTP_FORMAT_UNDEFINED_AUDIO", 0xB900 },
{ "MTP_FORMAT_WMA", 0xB901 },
{ "MTP_FORMAT_OGG", 0xB902 },
{ "MTP_FORMAT_AAC", 0xB903 },
{ "MTP_FORMAT_AUDIBLE", 0xB904 },
{ "MTP_FORMAT_FLAC", 0xB906 },
{ "MTP_FORMAT_UNDEFINED_VIDEO", 0xB980 },
{ "MTP_FORMAT_WMV", 0xB981 },
{ "MTP_FORMAT_MP4_CONTAINER", 0xB982 },
{ "MTP_FORMAT_MP2", 0xB983 },
{ "MTP_FORMAT_3GP_CONTAINER", 0xB984 },
{ "MTP_FORMAT_UNDEFINED_COLLECTION", 0xBA00 },
{ "MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM", 0xBA01 },
{ "MTP_FORMAT_ABSTRACT_IMAGE_ALBUM", 0xBA02 },
{ "MTP_FORMAT_ABSTRACT_AUDIO_ALBUM", 0xBA03 },
{ "MTP_FORMAT_ABSTRACT_VIDEO_ALBUM", 0xBA04 },
{ "MTP_FORMAT_ABSTRACT_AV_PLAYLIST", 0xBA05 },
{ "MTP_FORMAT_ABSTRACT_CONTACT_GROUP", 0xBA06 },
{ "MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER", 0xBA07 },
{ "MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION", 0xBA08 },
{ "MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST", 0xBA09 },
{ "MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST", 0xBA0A },
{ "MTP_FORMAT_ABSTRACT_MEDIACAST", 0xBA0B },
{ "MTP_FORMAT_WPL_PLAYLIST", 0xBA10 },
{ "MTP_FORMAT_M3U_PLAYLIST", 0xBA11 },
{ "MTP_FORMAT_MPL_PLAYLIST", 0xBA12 },
{ "MTP_FORMAT_ASX_PLAYLIST", 0xBA13 },
{ "MTP_FORMAT_PLS_PLAYLIST", 0xBA14 },
{ "MTP_FORMAT_UNDEFINED_DOCUMENT", 0xBA80 },
{ "MTP_FORMAT_ABSTRACT_DOCUMENT", 0xBA81 },
{ "MTP_FORMAT_XML_DOCUMENT", 0xBA82 },
{ "MTP_FORMAT_MS_WORD_DOCUMENT", 0xBA83 },
{ "MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT", 0xBA84 },
{ "MTP_FORMAT_MS_EXCEL_SPREADSHEET", 0xBA85 },
{ "MTP_FORMAT_MS_POWERPOINT_PRESENTATION", 0xBA86 },
{ "MTP_FORMAT_UNDEFINED_MESSAGE", 0xBB00 },
{ "MTP_FORMAT_ABSTRACT_MESSSAGE", 0xBB01 },
{ "MTP_FORMAT_UNDEFINED_CONTACT", 0xBB80 },
{ "MTP_FORMAT_ABSTRACT_CONTACT", 0xBB81 },
{ "MTP_FORMAT_VCARD_2", 0xBB82 },
{ 0, 0 },
};
static const CodeEntry sObjectPropCodes[] = {
{ "MTP_PROPERTY_STORAGE_ID", 0xDC01 },
{ "MTP_PROPERTY_OBJECT_FORMAT", 0xDC02 },
{ "MTP_PROPERTY_PROTECTION_STATUS", 0xDC03 },
{ "MTP_PROPERTY_OBJECT_SIZE", 0xDC04 },
{ "MTP_PROPERTY_ASSOCIATION_TYPE", 0xDC05 },
{ "MTP_PROPERTY_ASSOCIATION_DESC", 0xDC06 },
{ "MTP_PROPERTY_OBJECT_FILE_NAME", 0xDC07 },
{ "MTP_PROPERTY_DATE_CREATED", 0xDC08 },
{ "MTP_PROPERTY_DATE_MODIFIED", 0xDC09 },
{ "MTP_PROPERTY_KEYWORDS", 0xDC0A },
{ "MTP_PROPERTY_PARENT_OBJECT", 0xDC0B },
{ "MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS", 0xDC0C },
{ "MTP_PROPERTY_HIDDEN", 0xDC0D },
{ "MTP_PROPERTY_SYSTEM_OBJECT", 0xDC0E },
{ "MTP_PROPERTY_PERSISTENT_UID", 0xDC41 },
{ "MTP_PROPERTY_SYNC_ID", 0xDC42 },
{ "MTP_PROPERTY_PROPERTY_BAG", 0xDC43 },
{ "MTP_PROPERTY_NAME", 0xDC44 },
{ "MTP_PROPERTY_CREATED_BY", 0xDC45 },
{ "MTP_PROPERTY_ARTIST", 0xDC46 },
{ "MTP_PROPERTY_DATE_AUTHORED", 0xDC47 },
{ "MTP_PROPERTY_DESCRIPTION", 0xDC48 },
{ "MTP_PROPERTY_URL_REFERENCE", 0xDC49 },
{ "MTP_PROPERTY_LANGUAGE_LOCALE", 0xDC4A },
{ "MTP_PROPERTY_COPYRIGHT_INFORMATION", 0xDC4B },
{ "MTP_PROPERTY_SOURCE", 0xDC4C },
{ "MTP_PROPERTY_ORIGIN_LOCATION", 0xDC4D },
{ "MTP_PROPERTY_DATE_ADDED", 0xDC4E },
{ "MTP_PROPERTY_NON_CONSUMABLE", 0xDC4F },
{ "MTP_PROPERTY_CORRUPT_UNPLAYABLE", 0xDC50 },
{ "MTP_PROPERTY_PRODUCER_SERIAL_NUMBER", 0xDC51 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT", 0xDC81 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE", 0xDC82 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT", 0xDC83 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH", 0xDC84 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION", 0xDC85 },
{ "MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA", 0xDC86 },
{ "MTP_PROPERTY_WIDTH", 0xDC87 },
{ "MTP_PROPERTY_HEIGHT", 0xDC88 },
{ "MTP_PROPERTY_DURATION", 0xDC89 },
{ "MTP_PROPERTY_RATING", 0xDC8A },
{ "MTP_PROPERTY_TRACK", 0xDC8B },
{ "MTP_PROPERTY_GENRE", 0xDC8C },
{ "MTP_PROPERTY_CREDITS", 0xDC8D },
{ "MTP_PROPERTY_LYRICS", 0xDC8E },
{ "MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID", 0xDC8F },
{ "MTP_PROPERTY_PRODUCED_BY", 0xDC90 },
{ "MTP_PROPERTY_USE_COUNT", 0xDC91 },
{ "MTP_PROPERTY_SKIP_COUNT", 0xDC92 },
{ "MTP_PROPERTY_LAST_ACCESSED", 0xDC93 },
{ "MTP_PROPERTY_PARENTAL_RATING", 0xDC94 },
{ "MTP_PROPERTY_META_GENRE", 0xDC95 },
{ "MTP_PROPERTY_COMPOSER", 0xDC96 },
{ "MTP_PROPERTY_EFFECTIVE_RATING", 0xDC97 },
{ "MTP_PROPERTY_SUBTITLE", 0xDC98 },
{ "MTP_PROPERTY_ORIGINAL_RELEASE_DATE", 0xDC99 },
{ "MTP_PROPERTY_ALBUM_NAME", 0xDC9A },
{ "MTP_PROPERTY_ALBUM_ARTIST", 0xDC9B },
{ "MTP_PROPERTY_MOOD", 0xDC9C },
{ "MTP_PROPERTY_DRM_STATUS", 0xDC9D },
{ "MTP_PROPERTY_SUB_DESCRIPTION", 0xDC9E },
{ "MTP_PROPERTY_IS_CROPPED", 0xDCD1 },
{ "MTP_PROPERTY_IS_COLOUR_CORRECTED", 0xDCD2 },
{ "MTP_PROPERTY_IMAGE_BIT_DEPTH", 0xDCD3 },
{ "MTP_PROPERTY_F_NUMBER", 0xDCD4 },
{ "MTP_PROPERTY_EXPOSURE_TIME", 0xDCD5 },
{ "MTP_PROPERTY_EXPOSURE_INDEX", 0xDCD6 },
{ "MTP_PROPERTY_TOTAL_BITRATE", 0xDE91 },
{ "MTP_PROPERTY_BITRATE_TYPE", 0xDE92 },
{ "MTP_PROPERTY_SAMPLE_RATE", 0xDE93 },
{ "MTP_PROPERTY_NUMBER_OF_CHANNELS", 0xDE94 },
{ "MTP_PROPERTY_AUDIO_BIT_DEPTH", 0xDE95 },
{ "MTP_PROPERTY_SCAN_TYPE", 0xDE97 },
{ "MTP_PROPERTY_AUDIO_WAVE_CODEC", 0xDE99 },
{ "MTP_PROPERTY_AUDIO_BITRATE", 0xDE9A },
{ "MTP_PROPERTY_VIDEO_FOURCC_CODEC", 0xDE9B },
{ "MTP_PROPERTY_VIDEO_BITRATE", 0xDE9C },
{ "MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS", 0xDE9D },
{ "MTP_PROPERTY_KEYFRAME_DISTANCE", 0xDE9E },
{ "MTP_PROPERTY_BUFFER_SIZE", 0xDE9F },
{ "MTP_PROPERTY_ENCODING_QUALITY", 0xDEA0 },
{ "MTP_PROPERTY_ENCODING_PROFILE", 0xDEA1 },
{ "MTP_PROPERTY_DISPLAY_NAME", 0xDCE0 },
{ "MTP_PROPERTY_BODY_TEXT", 0xDCE1 },
{ "MTP_PROPERTY_SUBJECT", 0xDCE2 },
{ "MTP_PROPERTY_PRIORITY", 0xDCE3 },
{ "MTP_PROPERTY_GIVEN_NAME", 0xDD00 },
{ "MTP_PROPERTY_MIDDLE_NAMES", 0xDD01 },
{ "MTP_PROPERTY_FAMILY_NAME", 0xDD02 },
{ "MTP_PROPERTY_PREFIX", 0xDD03 },
{ "MTP_PROPERTY_SUFFIX", 0xDD04 },
{ "MTP_PROPERTY_PHONETIC_GIVEN_NAME", 0xDD05 },
{ "MTP_PROPERTY_PHONETIC_FAMILY_NAME", 0xDD06 },
{ "MTP_PROPERTY_EMAIL_PRIMARY", 0xDD07 },
{ "MTP_PROPERTY_EMAIL_PERSONAL_1", 0xDD08 },
{ "MTP_PROPERTY_EMAIL_PERSONAL_2", 0xDD09 },
{ "MTP_PROPERTY_EMAIL_BUSINESS_1", 0xDD0A },
{ "MTP_PROPERTY_EMAIL_BUSINESS_2", 0xDD0B },
{ "MTP_PROPERTY_EMAIL_OTHERS", 0xDD0C },
{ "MTP_PROPERTY_PHONE_NUMBER_PRIMARY", 0xDD0D },
{ "MTP_PROPERTY_PHONE_NUMBER_PERSONAL", 0xDD0E },
{ "MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2", 0xDD0F },
{ "MTP_PROPERTY_PHONE_NUMBER_BUSINESS", 0xDD10 },
{ "MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2", 0xDD11 },
{ "MTP_PROPERTY_PHONE_NUMBER_MOBILE", 0xDD12 },
{ "MTP_PROPERTY_PHONE_NUMBER_MOBILE_2", 0xDD13 },
{ "MTP_PROPERTY_FAX_NUMBER_PRIMARY", 0xDD14 },
{ "MTP_PROPERTY_FAX_NUMBER_PERSONAL", 0xDD15 },
{ "MTP_PROPERTY_FAX_NUMBER_BUSINESS", 0xDD16 },
{ "MTP_PROPERTY_PAGER_NUMBER", 0xDD17 },
{ "MTP_PROPERTY_PHONE_NUMBER_OTHERS", 0xDD18 },
{ "MTP_PROPERTY_PRIMARY_WEB_ADDRESS", 0xDD19 },
{ "MTP_PROPERTY_PERSONAL_WEB_ADDRESS", 0xDD1A },
{ "MTP_PROPERTY_BUSINESS_WEB_ADDRESS", 0xDD1B },
{ "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS", 0xDD1C },
{ "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2", 0xDD1D },
{ "MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3", 0xDD1E },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL", 0xDD1F },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1", 0xDD20 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2", 0xDD21 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY", 0xDD22 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION", 0xDD23 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE", 0xDD24 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY", 0xDD25 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL", 0xDD26 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1", 0xDD27 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2", 0xDD28 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY", 0xDD29 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION", 0xDD2A },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE", 0xDD2B },
{ "MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY", 0xDD2C },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL", 0xDD2D },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1", 0xDD2E },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2", 0xDD2F },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY", 0xDD30 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION", 0xDD31 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE", 0xDD32 },
{ "MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY", 0xDD33 },
{ "MTP_PROPERTY_ORGANIZATION_NAME", 0xDD34 },
{ "MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME", 0xDD35 },
{ "MTP_PROPERTY_ROLE", 0xDD36 },
{ "MTP_PROPERTY_BIRTHDATE", 0xDD37 },
{ "MTP_PROPERTY_MESSAGE_TO", 0xDD40 },
{ "MTP_PROPERTY_MESSAGE_CC", 0xDD41 },
{ "MTP_PROPERTY_MESSAGE_BCC", 0xDD42 },
{ "MTP_PROPERTY_MESSAGE_READ", 0xDD43 },
{ "MTP_PROPERTY_MESSAGE_RECEIVED_TIME", 0xDD44 },
{ "MTP_PROPERTY_MESSAGE_SENDER", 0xDD45 },
{ "MTP_PROPERTY_ACTIVITY_BEGIN_TIME", 0xDD50 },
{ "MTP_PROPERTY_ACTIVITY_END_TIME", 0xDD51 },
{ "MTP_PROPERTY_ACTIVITY_LOCATION", 0xDD52 },
{ "MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES", 0xDD54 },
{ "MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES", 0xDD55 },
{ "MTP_PROPERTY_ACTIVITY_RESOURCES", 0xDD56 },
{ "MTP_PROPERTY_ACTIVITY_ACCEPTED", 0xDD57 },
{ "MTP_PROPERTY_ACTIVITY_TENTATIVE", 0xDD58 },
{ "MTP_PROPERTY_ACTIVITY_DECLINED", 0xDD59 },
{ "MTP_PROPERTY_ACTIVITY_REMAINDER_TIME", 0xDD5A },
{ "MTP_PROPERTY_ACTIVITY_OWNER", 0xDD5B },
{ "MTP_PROPERTY_ACTIVITY_STATUS", 0xDD5C },
{ "MTP_PROPERTY_OWNER", 0xDD5D },
{ "MTP_PROPERTY_EDITOR", 0xDD5E },
{ "MTP_PROPERTY_WEBMASTER", 0xDD5F },
{ "MTP_PROPERTY_URL_SOURCE", 0xDD60 },
{ "MTP_PROPERTY_URL_DESTINATION", 0xDD61 },
{ "MTP_PROPERTY_TIME_BOOKMARK", 0xDD62 },
{ "MTP_PROPERTY_OBJECT_BOOKMARK", 0xDD63 },
{ "MTP_PROPERTY_BYTE_BOOKMARK", 0xDD64 },
{ "MTP_PROPERTY_LAST_BUILD_DATE", 0xDD70 },
{ "MTP_PROPERTY_TIME_TO_LIVE", 0xDD71 },
{ "MTP_PROPERTY_MEDIA_GUID", 0xDD72 },
{ 0, 0 },
};
static const CodeEntry sDevicePropCodes[] = {
{ "MTP_DEVICE_PROPERTY_UNDEFINED", 0x5000 },
{ "MTP_DEVICE_PROPERTY_BATTERY_LEVEL", 0x5001 },
{ "MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE", 0x5002 },
{ "MTP_DEVICE_PROPERTY_IMAGE_SIZE", 0x5003 },
{ "MTP_DEVICE_PROPERTY_COMPRESSION_SETTING", 0x5004 },
{ "MTP_DEVICE_PROPERTY_WHITE_BALANCE", 0x5005 },
{ "MTP_DEVICE_PROPERTY_RGB_GAIN", 0x5006 },
{ "MTP_DEVICE_PROPERTY_F_NUMBER", 0x5007 },
{ "MTP_DEVICE_PROPERTY_FOCAL_LENGTH", 0x5008 },
{ "MTP_DEVICE_PROPERTY_FOCUS_DISTANCE", 0x5009 },
{ "MTP_DEVICE_PROPERTY_FOCUS_MODE", 0x500A },
{ "MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE", 0x500B },
{ "MTP_DEVICE_PROPERTY_FLASH_MODE", 0x500C },
{ "MTP_DEVICE_PROPERTY_EXPOSURE_TIME", 0x500D },
{ "MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE", 0x500E },
{ "MTP_DEVICE_PROPERTY_EXPOSURE_INDEX", 0x500F },
{ "MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION", 0x5010 },
{ "MTP_DEVICE_PROPERTY_DATETIME", 0x5011 },
{ "MTP_DEVICE_PROPERTY_CAPTURE_DELAY", 0x5012 },
{ "MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE", 0x5013 },
{ "MTP_DEVICE_PROPERTY_CONTRAST", 0x5014 },
{ "MTP_DEVICE_PROPERTY_SHARPNESS", 0x5015 },
{ "MTP_DEVICE_PROPERTY_DIGITAL_ZOOM", 0x5016 },
{ "MTP_DEVICE_PROPERTY_EFFECT_MODE", 0x5017 },
{ "MTP_DEVICE_PROPERTY_BURST_NUMBER", 0x5018 },
{ "MTP_DEVICE_PROPERTY_BURST_INTERVAL", 0x5019 },
{ "MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER", 0x501A },
{ "MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL", 0x501B },
{ "MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE", 0x501C },
{ "MTP_DEVICE_PROPERTY_UPLOAD_URL", 0x501D },
{ "MTP_DEVICE_PROPERTY_ARTIST", 0x501E },
{ "MTP_DEVICE_PROPERTY_COPYRIGHT_INFO", 0x501F },
{ "MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER", 0xD401 },
{ "MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME", 0xD402 },
{ "MTP_DEVICE_PROPERTY_VOLUME", 0xD403 },
{ "MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED", 0xD404 },
{ "MTP_DEVICE_PROPERTY_DEVICE_ICON", 0xD405 },
{ "MTP_DEVICE_PROPERTY_PLAYBACK_RATE", 0xD410 },
{ "MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT", 0xD411 },
{ "MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX", 0xD412 },
{ "MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO", 0xD406 },
{ "MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE", 0xD407 },
{ 0, 0 },
};
static const char* getCodeName(uint16_t code, const CodeEntry* table) {
const CodeEntry* entry = table;
while (entry->name) {
if (entry->code == code)
return entry->name;
entry++;
}
return "UNKNOWN";
}
const char* MtpDebug::getOperationCodeName(MtpOperationCode code) {
return getCodeName(code, sOperationCodes);
}
const char* MtpDebug::getFormatCodeName(MtpObjectFormat code) {
if (code == 0)
return "NONE";
return getCodeName(code, sFormatCodes);
}
const char* MtpDebug::getObjectPropCodeName(MtpPropertyCode code) {
if (code == 0)
return "NONE";
return getCodeName(code, sObjectPropCodes);
}
const char* MtpDebug::getDevicePropCodeName(MtpPropertyCode code) {
if (code == 0)
return "NONE";
return getCodeName(code, sDevicePropCodes);
}
Executable
+49
View File
@@ -0,0 +1,49 @@
/*
* 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++
*/
#ifndef _MTP_DEBUG_H
#define _MTP_DEBUG_H
// #define LOG_NDEBUG 0
#include <utils/Log.h>
#include "MtpTypes.h"
#ifdef __cplusplus
extern "C" {
#endif
void mtpdebug(const char *fmt, ...);
#define MTPI(...) fprintf(stdout, __VA_ARGS__)
#define MTPD(...) mtpdebug(__VA_ARGS__)
#define MTPE(...) fprintf(stdout, "E:" __VA_ARGS__)
#ifdef __cplusplus
}
#endif
class MtpDebug {
public:
static const char* getOperationCodeName(MtpOperationCode code);
static const char* getFormatCodeName(MtpObjectFormat code);
static const char* getObjectPropCodeName(MtpPropertyCode code);
static const char* getDevicePropCodeName(MtpPropertyCode code);
};
#endif // _MTP_DEBUG_H
+833
View File
@@ -0,0 +1,833 @@
/*
* 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 "MtpDevice.h"
#include "MtpDebug.h"
#include "MtpDeviceInfo.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpStorageInfo.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
#include "MtpDataPacket.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <endian.h>
#include <usbhost/usbhost.h>
#if 0
static bool isMtpDevice(uint16_t vendor, uint16_t product) {
// Sandisk Sansa Fuze
if (vendor == 0x0781 && product == 0x74c2)
return true;
// Samsung YP-Z5
if (vendor == 0x04e8 && product == 0x503c)
return true;
return false;
}
#endif
MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
struct usb_device *device = usb_device_new(deviceName, fd);
if (!device) {
MTPE("usb_device_new failed for %s", deviceName);
return NULL;
}
struct usb_descriptor_header* desc;
struct usb_descriptor_iter iter;
usb_descriptor_iter_init(device, &iter);
while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
if (desc->bDescriptorType == USB_DT_INTERFACE) {
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
interface->bInterfaceSubClass == 1 && // Still Image Capture
interface->bInterfaceProtocol == 1) // Picture Transfer Protocol (PIMA 15470)
{
char* manufacturerName = usb_device_get_manufacturer_name(device);
char* productName = usb_device_get_product_name(device);
MTPD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
free(manufacturerName);
free(productName);
} else if (interface->bInterfaceClass == 0xFF &&
interface->bInterfaceSubClass == 0xFF &&
interface->bInterfaceProtocol == 0) {
char* interfaceName = usb_device_get_string(device, interface->iInterface);
if (!interfaceName) {
continue;
} else if (strcmp(interfaceName, "MTP")) {
free(interfaceName);
continue;
}
free(interfaceName);
// Looks like an android style MTP device
char* manufacturerName = usb_device_get_manufacturer_name(device);
char* productName = usb_device_get_product_name(device);
MTPI("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
free(manufacturerName);
free(productName);
}
#if 0
else {
// look for special cased devices based on vendor/product ID
// we are doing this mainly for testing purposes
uint16_t vendor = usb_device_get_vendor_id(device);
uint16_t product = usb_device_get_product_id(device);
if (!isMtpDevice(vendor, product)) {
// not an MTP or PTP device
continue;
}
// request MTP OS string and descriptor
// some music players need to see this before entering MTP mode.
char buffer[256];
memset(buffer, 0, sizeof(buffer));
int ret = usb_device_control_transfer(device,
USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
0, buffer, sizeof(buffer), 0);
MTPE("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
if (ret > 0) {
MTPI("got MTP string %s\n", buffer);
ret = usb_device_control_transfer(device,
USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
0, 4, buffer, sizeof(buffer), 0);
MTPI("OS descriptor got %d\n", ret);
} else {
MTPI("no MTP string\n");
}
}
#endif
// if we got here, then we have a likely MTP or PTP device
// interface should be followed by three endpoints
struct usb_endpoint_descriptor *ep;
struct usb_endpoint_descriptor *ep_in_desc = NULL;
struct usb_endpoint_descriptor *ep_out_desc = NULL;
struct usb_endpoint_descriptor *ep_intr_desc = NULL;
for (int i = 0; i < 3; i++) {
ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
MTPE("endpoints not found\n");
usb_device_close(device);
return NULL;
}
if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
ep_in_desc = ep;
else
ep_out_desc = ep;
} else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
ep_intr_desc = ep;
}
}
if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
MTPE("endpoints not found\n");
usb_device_close(device);
return NULL;
}
if (usb_device_claim_interface(device, interface->bInterfaceNumber)) {
MTPE("usb_device_claim_interface failed errno: %d\n", errno);
usb_device_close(device);
return NULL;
}
MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
ep_in_desc, ep_out_desc, ep_intr_desc);
mtpDevice->initialize();
return mtpDevice;
}
}
usb_device_close(device);
MTPE("device not found");
return NULL;
}
MtpDevice::MtpDevice(struct usb_device* device, int interface,
const struct usb_endpoint_descriptor *ep_in,
const struct usb_endpoint_descriptor *ep_out,
const struct usb_endpoint_descriptor *ep_intr)
: mDevice(device),
mInterface(interface),
mRequestIn1(NULL),
mRequestIn2(NULL),
mRequestOut(NULL),
mRequestIntr(NULL),
mDeviceInfo(NULL),
mSessionID(0),
mTransactionID(0),
mReceivedResponse(false)
{
mRequestIn1 = usb_request_new(device, ep_in);
mRequestIn2 = usb_request_new(device, ep_in);
mRequestOut = usb_request_new(device, ep_out);
mRequestIntr = usb_request_new(device, ep_intr);
}
MtpDevice::~MtpDevice() {
close();
for (size_t i = 0; i < mDeviceProperties.size(); i++)
delete mDeviceProperties[i];
usb_request_free(mRequestIn1);
usb_request_free(mRequestIn2);
usb_request_free(mRequestOut);
usb_request_free(mRequestIntr);
}
void MtpDevice::initialize() {
openSession();
mDeviceInfo = getDeviceInfo();
if (mDeviceInfo) {
if (mDeviceInfo->mDeviceProperties) {
int count = mDeviceInfo->mDeviceProperties->size();
for (int i = 0; i < count; i++) {
MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
MtpProperty* property = getDevicePropDesc(propCode);
if (property)
mDeviceProperties.push(property);
}
}
}
}
void MtpDevice::close() {
if (mDevice) {
usb_device_release_interface(mDevice, mInterface);
usb_device_close(mDevice);
mDevice = NULL;
}
}
void MtpDevice::print() {
if (mDeviceInfo) {
mDeviceInfo->print();
if (mDeviceInfo->mDeviceProperties) {
MTPI("***** DEVICE PROPERTIES *****\n");
int count = mDeviceInfo->mDeviceProperties->size();
for (int i = 0; i < count; i++) {
MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
MtpProperty* property = getDevicePropDesc(propCode);
if (property) {
property->print();
delete property;
}
}
}
}
if (mDeviceInfo->mPlaybackFormats) {
MTPI("***** OBJECT PROPERTIES *****\n");
int count = mDeviceInfo->mPlaybackFormats->size();
for (int i = 0; i < count; i++) {
MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
MTPI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
MtpObjectPropertyList* props = getObjectPropsSupported(format);
if (props) {
for (size_t j = 0; j < props->size(); j++) {
MtpObjectProperty prop = (*props)[j];
MtpProperty* property = getObjectPropDesc(prop, format);
if (property) {
property->print();
delete property;
} else {
MTPI("could not fetch property: %s",
MtpDebug::getObjectPropCodeName(prop));
}
}
}
}
}
}
const char* MtpDevice::getDeviceName() {
if (mDevice)
return usb_device_get_name(mDevice);
else
return "???";
}
bool MtpDevice::openSession() {
android::Mutex::Autolock autoLock(mMutex);
mSessionID = 0;
mTransactionID = 0;
MtpSessionID newSession = 1;
mRequest.reset();
mRequest.setParameter(1, newSession);
if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
return false;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
newSession = mResponse.getParameter(1);
else if (ret != MTP_RESPONSE_OK)
return false;
mSessionID = newSession;
mTransactionID = 1;
return true;
}
bool MtpDevice::closeSession() {
// FIXME
return true;
}
MtpDeviceInfo* MtpDevice::getDeviceInfo() {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpDeviceInfo* info = new MtpDeviceInfo;
info->read(mData);
return info;
}
return NULL;
}
MtpStorageIDList* MtpDevice::getStorageIDs() {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
return mData.getAUInt32();
}
return NULL;
}
MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, storageID);
if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpStorageInfo* info = new MtpStorageInfo(storageID);
info->read(mData);
return info;
}
return NULL;
}
MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
MtpObjectFormat format, MtpObjectHandle parent) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, storageID);
mRequest.setParameter(2, format);
mRequest.setParameter(3, parent);
if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
return mData.getAUInt32();
}
return NULL;
}
MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
android::Mutex::Autolock autoLock(mMutex);
// FIXME - we might want to add some caching here
mRequest.reset();
mRequest.setParameter(1, handle);
if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpObjectInfo* info = new MtpObjectInfo(handle);
info->read(mData);
return info;
}
return NULL;
}
void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, handle);
if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
return mData.getData(outLength);
}
}
outLength = 0;
return NULL;
}
MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
MtpObjectHandle parent = info->mParent;
if (parent == 0)
parent = MTP_PARENT_ROOT;
mRequest.setParameter(1, info->mStorageID);
mRequest.setParameter(2, info->mParent);
mData.putUInt32(info->mStorageID);
mData.putUInt16(info->mFormat);
mData.putUInt16(info->mProtectionStatus);
mData.putUInt32(info->mCompressedSize);
mData.putUInt16(info->mThumbFormat);
mData.putUInt32(info->mThumbCompressedSize);
mData.putUInt32(info->mThumbPixWidth);
mData.putUInt32(info->mThumbPixHeight);
mData.putUInt32(info->mImagePixWidth);
mData.putUInt32(info->mImagePixHeight);
mData.putUInt32(info->mImagePixDepth);
mData.putUInt32(info->mParent);
mData.putUInt16(info->mAssociationType);
mData.putUInt32(info->mAssociationDesc);
mData.putUInt32(info->mSequenceNumber);
mData.putString(info->mName);
char created[100], modified[100];
formatDateTime(info->mDateCreated, created, sizeof(created));
formatDateTime(info->mDateModified, modified, sizeof(modified));
mData.putString(created);
mData.putString(modified);
if (info->mKeywords)
mData.putString(info->mKeywords);
else
mData.putEmptyString();
if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
info->mStorageID = mResponse.getParameter(1);
info->mParent = mResponse.getParameter(2);
info->mHandle = mResponse.getParameter(3);
return info->mHandle;
}
}
return (MtpObjectHandle)-1;
}
bool MtpDevice::sendObject(MtpObjectInfo* info, int srcFD) {
android::Mutex::Autolock autoLock(mMutex);
int remaining = info->mCompressedSize;
mRequest.reset();
mRequest.setParameter(1, info->mHandle);
if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
// send data header
writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
char buffer[65536];
while (remaining > 0) {
int count = read(srcFD, buffer, sizeof(buffer));
if (count > 0) {
int written = mData.write(mRequestOut, buffer, count);
// FIXME check error
remaining -= count;
} else {
break;
}
}
}
MtpResponseCode ret = readResponse();
return (remaining == 0 && ret == MTP_RESPONSE_OK);
}
bool MtpDevice::deleteObject(MtpObjectHandle handle) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, handle);
if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK)
return true;
}
return false;
}
MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
MtpObjectInfo* info = getObjectInfo(handle);
if (info) {
MtpObjectHandle parent = info->mParent;
delete info;
return parent;
} else {
return -1;
}
}
MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
MtpObjectInfo* info = getObjectInfo(handle);
if (info) {
MtpObjectHandle storageId = info->mStorageID;
delete info;
return storageId;
} else {
return -1;
}
}
MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, format);
if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
return mData.getAUInt16();
}
return NULL;
}
MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, code);
if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpProperty* property = new MtpProperty;
property->read(mData);
return property;
}
return NULL;
}
MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
android::Mutex::Autolock autoLock(mMutex);
mRequest.reset();
mRequest.setParameter(1, code);
mRequest.setParameter(2, format);
if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
return NULL;
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
if (ret == MTP_RESPONSE_OK) {
MtpProperty* property = new MtpProperty;
property->read(mData);
return property;
}
return NULL;
}
bool MtpDevice::readObject(MtpObjectHandle handle,
bool (* callback)(void* data, int offset, int length, void* clientData),
int objectSize, void* clientData) {
android::Mutex::Autolock autoLock(mMutex);
bool result = false;
mRequest.reset();
mRequest.setParameter(1, handle);
if (sendRequest(MTP_OPERATION_GET_OBJECT)
&& mData.readDataHeader(mRequestIn1)) {
uint32_t length = mData.getContainerLength();
if ((int)length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
MTPE("readObject error objectSize: %d, length: %d",
objectSize, length);
goto fail;
}
length -= MTP_CONTAINER_HEADER_SIZE;
uint32_t remaining = length;
int offset = 0;
int initialDataLength = 0;
void* initialData = mData.getData(initialDataLength);
if (initialData) {
if (initialDataLength > 0) {
if (!callback(initialData, 0, initialDataLength, clientData))
goto fail;
remaining -= initialDataLength;
offset += initialDataLength;
}
free(initialData);
}
// USB reads greater than 16K don't work
char buffer1[16384], buffer2[16384];
mRequestIn1->buffer = buffer1;
mRequestIn2->buffer = buffer2;
struct usb_request* req = mRequestIn1;
void* writeBuffer = NULL;
int writeLength = 0;
while (remaining > 0 || writeBuffer) {
if (remaining > 0) {
// queue up a read request
req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
if (mData.readDataAsync(req)) {
MTPE("readDataAsync failed");
goto fail;
}
} else {
req = NULL;
}
if (writeBuffer) {
// write previous buffer
if (!callback(writeBuffer, offset, writeLength, clientData)) {
MTPE("write failed");
// wait for pending read before failing
if (req)
mData.readDataWait(mDevice);
goto fail;
}
offset += writeLength;
writeBuffer = NULL;
}
// wait for read to complete
if (req) {
int read = mData.readDataWait(mDevice);
if (read < 0)
goto fail;
if (read > 0) {
writeBuffer = req->buffer;
writeLength = read;
remaining -= read;
req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
} else {
writeBuffer = NULL;
}
}
}
MtpResponseCode response = readResponse();
if (response == MTP_RESPONSE_OK)
result = true;
}
fail:
return result;
}
// reads the object's data and writes it to the specified file path
bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
MTPI("readObject: %s", destPath);
int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, 0640);
if (fd < 0) {
MTPE("open failed for %s", destPath);
return false;
}
fchown(fd, getuid(), group);
// set permissions
int mask = umask(0);
fchmod(fd, perm);
umask(mask);
android::Mutex::Autolock autoLock(mMutex);
bool result = false;
mRequest.reset();
mRequest.setParameter(1, handle);
if (sendRequest(MTP_OPERATION_GET_OBJECT)
&& mData.readDataHeader(mRequestIn1)) {
uint32_t length = mData.getContainerLength();
if (length < MTP_CONTAINER_HEADER_SIZE)
goto fail;
length -= MTP_CONTAINER_HEADER_SIZE;
uint32_t remaining = length;
int initialDataLength = 0;
void* initialData = mData.getData(initialDataLength);
if (initialData) {
if (initialDataLength > 0) {
if (write(fd, initialData, initialDataLength) != initialDataLength) {
free(initialData);
goto fail;
}
remaining -= initialDataLength;
}
free(initialData);
}
// USB reads greater than 16K don't work
char buffer1[16384], buffer2[16384];
mRequestIn1->buffer = buffer1;
mRequestIn2->buffer = buffer2;
struct usb_request* req = mRequestIn1;
void* writeBuffer = NULL;
int writeLength = 0;
while (remaining > 0 || writeBuffer) {
if (remaining > 0) {
// queue up a read request
req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
if (mData.readDataAsync(req)) {
MTPE("readDataAsync failed");
goto fail;
}
} else {
req = NULL;
}
if (writeBuffer) {
// write previous buffer
if (write(fd, writeBuffer, writeLength) != writeLength) {
MTPE("write failed");
// wait for pending read before failing
if (req)
mData.readDataWait(mDevice);
goto fail;
}
writeBuffer = NULL;
}
// wait for read to complete
if (req) {
int read = mData.readDataWait(mDevice);
if (read < 0)
goto fail;
if (read > 0) {
writeBuffer = req->buffer;
writeLength = read;
remaining -= read;
req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
} else {
writeBuffer = NULL;
}
}
}
MtpResponseCode response = readResponse();
if (response == MTP_RESPONSE_OK)
result = true;
}
fail:
::close(fd);
return result;
}
bool MtpDevice::sendRequest(MtpOperationCode operation) {
MTPD("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
mReceivedResponse = false;
mRequest.setOperationCode(operation);
if (mTransactionID > 0)
mRequest.setTransactionID(mTransactionID++);
int ret = mRequest.write(mRequestOut);
mRequest.dump();
return (ret > 0);
}
bool MtpDevice::sendData() {
MTPD("sendData\n");
mData.setOperationCode(mRequest.getOperationCode());
mData.setTransactionID(mRequest.getTransactionID());
int ret = mData.write(mRequestOut);
mData.dump();
return (ret > 0);
}
bool MtpDevice::readData() {
mData.reset();
int ret = mData.read(mRequestIn1);
MTPD("readData returned %d\n", ret);
if (ret >= MTP_CONTAINER_HEADER_SIZE) {
if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
MTPD("got response packet instead of data packet");
// we got a response packet rather than data
// copy it to mResponse
mResponse.copyFrom(mData);
mReceivedResponse = true;
return false;
}
mData.dump();
return true;
}
else {
MTPE("readResponse failed\n");
return false;
}
}
bool MtpDevice::writeDataHeader(MtpOperationCode operation, int dataLength) {
mData.setOperationCode(operation);
mData.setTransactionID(mRequest.getTransactionID());
return (!mData.writeDataHeader(mRequestOut, dataLength));
}
MtpResponseCode MtpDevice::readResponse() {
MTPD("readResponse\n");
if (mReceivedResponse) {
mReceivedResponse = false;
return mResponse.getResponseCode();
}
int ret = mResponse.read(mRequestIn1);
// handle zero length packets, which might occur if the data transfer
// ends on a packet boundary
if (ret == 0)
ret = mResponse.read(mRequestIn1);
if (ret >= MTP_CONTAINER_HEADER_SIZE) {
mResponse.dump();
return mResponse.getResponseCode();
} else {
MTPE("readResponse failed\n");
return -1;
}
}
+116
View File
@@ -0,0 +1,116 @@
/*
* 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++
*/
#ifndef _MTP_DEVICE_H
#define _MTP_DEVICE_H
#include "MtpRequestPacket.h"
#include "MtpDataPacket.h"
#include "MtpResponsePacket.h"
#include "MtpTypes.h"
#include <utils/threads.h>
struct usb_device;
struct usb_request;
struct usb_endpoint_descriptor;
class MtpDeviceInfo;
class MtpObjectInfo;
class MtpStorageInfo;
class MtpDevice {
private:
struct usb_device* mDevice;
int mInterface;
struct usb_request* mRequestIn1;
struct usb_request* mRequestIn2;
struct usb_request* mRequestOut;
struct usb_request* mRequestIntr;
MtpDeviceInfo* mDeviceInfo;
MtpPropertyList mDeviceProperties;
// current session ID
MtpSessionID mSessionID;
// current transaction ID
MtpTransactionID mTransactionID;
MtpRequestPacket mRequest;
MtpDataPacket mData;
MtpResponsePacket mResponse;
// set to true if we received a response packet instead of a data packet
bool mReceivedResponse;
// to ensure only one MTP transaction at a time
android::Mutex mMutex;
public:
MtpDevice(struct usb_device* device, int interface,
const struct usb_endpoint_descriptor *ep_in,
const struct usb_endpoint_descriptor *ep_out,
const struct usb_endpoint_descriptor *ep_intr);
static MtpDevice* open(const char* deviceName, int fd);
virtual ~MtpDevice();
void initialize();
void close();
void print();
const char* getDeviceName();
bool openSession();
bool closeSession();
MtpDeviceInfo* getDeviceInfo();
MtpStorageIDList* getStorageIDs();
MtpStorageInfo* getStorageInfo(MtpStorageID storageID);
MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format,
MtpObjectHandle parent);
MtpObjectInfo* getObjectInfo(MtpObjectHandle handle);
void* getThumbnail(MtpObjectHandle handle, int& outLength);
MtpObjectHandle sendObjectInfo(MtpObjectInfo* info);
bool sendObject(MtpObjectInfo* info, int srcFD);
bool deleteObject(MtpObjectHandle handle);
MtpObjectHandle getParent(MtpObjectHandle handle);
MtpObjectHandle getStorageID(MtpObjectHandle handle);
MtpObjectPropertyList* getObjectPropsSupported(MtpObjectFormat format);
MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
MtpProperty* getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
bool readObject(MtpObjectHandle handle,
bool (* callback)(void* data, int offset,
int length, void* clientData),
int objectSize, void* clientData);
bool readObject(MtpObjectHandle handle, const char* destPath, int group,
int perm);
private:
bool sendRequest(MtpOperationCode operation);
bool sendData();
bool readData();
bool writeDataHeader(MtpOperationCode operation, int dataLength);
MtpResponseCode readResponse();
};
#endif // _MTP_DEVICE_H
+94
View File
@@ -0,0 +1,94 @@
/*
* 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 "MtpDebug.h"
#include "MtpDataPacket.h"
#include "MtpDeviceInfo.h"
#include "MtpStringBuffer.h"
MtpDeviceInfo::MtpDeviceInfo()
: mStandardVersion(0),
mVendorExtensionID(0),
mVendorExtensionVersion(0),
mVendorExtensionDesc(NULL),
mFunctionalCode(0),
mOperations(NULL),
mEvents(NULL),
mDeviceProperties(NULL),
mCaptureFormats(NULL),
mPlaybackFormats(NULL),
mManufacturer(NULL),
mModel(NULL),
mVersion(NULL),
mSerial(NULL)
{
}
MtpDeviceInfo::~MtpDeviceInfo() {
if (mVendorExtensionDesc)
free(mVendorExtensionDesc);
delete mOperations;
delete mEvents;
delete mDeviceProperties;
delete mCaptureFormats;
delete mPlaybackFormats;
if (mManufacturer)
free(mManufacturer);
if (mModel)
free(mModel);
if (mVersion)
free(mVersion);
if (mSerial)
free(mSerial);
}
void MtpDeviceInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
// read the device info
mStandardVersion = packet.getUInt16();
mVendorExtensionID = packet.getUInt32();
mVendorExtensionVersion = packet.getUInt16();
packet.getString(string);
mVendorExtensionDesc = strdup((const char *)string);
mFunctionalCode = packet.getUInt16();
mOperations = packet.getAUInt16();
mEvents = packet.getAUInt16();
mDeviceProperties = packet.getAUInt16();
mCaptureFormats = packet.getAUInt16();
mPlaybackFormats = packet.getAUInt16();
packet.getString(string);
mManufacturer = strdup((const char *)string);
packet.getString(string);
mModel = strdup((const char *)string);
packet.getString(string);
mVersion = strdup((const char *)string);
packet.getString(string);
mSerial = strdup((const char *)string);
}
void MtpDeviceInfo::print() {
MTPI("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
mStandardVersion, mVendorExtensionID, mVendorExtensionVersion);
MTPI("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
mVendorExtensionDesc, mFunctionalCode, mManufacturer, mModel, mVersion, mSerial);
}
+54
View File
@@ -0,0 +1,54 @@
/*
* 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++
*/
#ifndef _MTP_DEVICE_INFO_H
#define _MTP_DEVICE_INFO_H
struct stat;
class MtpDataPacket;
class MtpDeviceInfo {
public:
uint16_t mStandardVersion;
uint32_t mVendorExtensionID;
uint16_t mVendorExtensionVersion;
char* mVendorExtensionDesc;
uint16_t mFunctionalCode;
UInt16List* mOperations;
UInt16List* mEvents;
MtpDevicePropertyList* mDeviceProperties;
MtpObjectFormatList* mCaptureFormats;
MtpObjectFormatList* mPlaybackFormats;
char* mManufacturer;
char* mModel;
char* mVersion;
char* mSerial;
public:
MtpDeviceInfo();
virtual ~MtpDeviceInfo();
void read(MtpDataPacket& packet);
void print();
};
#endif // _MTP_DEVICE_INFO_H
+68
View File
@@ -0,0 +1,68 @@
/*
* 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 <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#ifdef MTP_DEVICE
#include <linux/usb/f_mtp.h>
#endif
#include "MtpEventPacket.h"
#include <usbhost/usbhost.h>
MtpEventPacket::MtpEventPacket()
: MtpPacket(512)
{
}
MtpEventPacket::~MtpEventPacket() {
}
#ifdef MTP_DEVICE
int MtpEventPacket::write(int fd) {
struct mtp_event event;
putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_EVENT);
event.data = mBuffer;
event.length = mPacketSize;
int ret = ::ioctl(fd, MTP_SEND_EVENT, (unsigned long)&event);
return (ret < 0 ? ret : 0);
}
#endif
#ifdef MTP_HOST
int MtpEventPacket::read(struct usb_request *request) {
request->buffer = mBuffer;
request->buffer_length = mBufferSize;
int ret = transfer(request);
if (ret >= 0)
mPacketSize = ret;
else
mPacketSize = 0;
return ret;
}
#endif
+46
View File
@@ -0,0 +1,46 @@
/*
* 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++
*/
#ifndef _MTP_EVENT_PACKET_H
#define _MTP_EVENT_PACKET_H
#include "MtpPacket.h"
#include "mtp.h"
class MtpEventPacket : public MtpPacket {
public:
MtpEventPacket();
virtual ~MtpEventPacket();
#ifdef MTP_DEVICE
// write our data to the given file descriptor
int write(int fd);
#endif
#ifdef MTP_HOST
// read our buffer with the given request
int read(struct usb_request *request);
#endif
inline MtpEventCode getEventCode() const { return getContainerCode(); }
inline void setEventCode(MtpEventCode code)
{ return setContainerCode(code); }
};
#endif // _MTP_EVENT_PACKET_H
+105
View File
@@ -0,0 +1,105 @@
/*
* 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 "MtpDebug.h"
#include "MtpDataPacket.h"
#include "MtpObjectInfo.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
MtpObjectInfo::MtpObjectInfo(MtpObjectHandle handle)
: mHandle(handle),
mStorageID(0),
mFormat(0),
mProtectionStatus(0),
mCompressedSize(0),
mThumbFormat(0),
mThumbCompressedSize(0),
mThumbPixWidth(0),
mThumbPixHeight(0),
mImagePixWidth(0),
mImagePixHeight(0),
mImagePixDepth(0),
mParent(0),
mAssociationType(0),
mAssociationDesc(0),
mSequenceNumber(0),
mName(NULL),
mDateCreated(0),
mDateModified(0),
mKeywords(NULL)
{
}
MtpObjectInfo::~MtpObjectInfo() {
if (mName)
free(mName);
if (mKeywords)
free(mKeywords);
}
void MtpObjectInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
time_t time;
mStorageID = packet.getUInt32();
mFormat = packet.getUInt16();
mProtectionStatus = packet.getUInt16();
mCompressedSize = packet.getUInt32();
mThumbFormat = packet.getUInt16();
mThumbCompressedSize = packet.getUInt32();
mThumbPixWidth = packet.getUInt32();
mThumbPixHeight = packet.getUInt32();
mImagePixWidth = packet.getUInt32();
mImagePixHeight = packet.getUInt32();
mImagePixDepth = packet.getUInt32();
mParent = packet.getUInt32();
mAssociationType = packet.getUInt16();
mAssociationDesc = packet.getUInt32();
mSequenceNumber = packet.getUInt32();
packet.getString(string);
mName = strdup((const char *)string);
packet.getString(string);
if (parseDateTime((const char*)string, time))
mDateCreated = time;
packet.getString(string);
if (parseDateTime((const char*)string, time))
mDateModified = time;
packet.getString(string);
mKeywords = strdup((const char *)string);
}
void MtpObjectInfo::print() {
MTPI("MtpObject Info %08X: %s\n", mHandle, mName);
MTPI(" mStorageID: %08X mFormat: %04X mProtectionStatus: %d\n",
mStorageID, mFormat, mProtectionStatus);
MTPI(" mCompressedSize: %d mThumbFormat: %04X mThumbCompressedSize: %d\n",
mCompressedSize, mFormat, mThumbCompressedSize);
MTPI(" mThumbPixWidth: %d mThumbPixHeight: %d\n", mThumbPixWidth, mThumbPixHeight);
MTPI(" mImagePixWidth: %d mImagePixHeight: %d mImagePixDepth: %d\n",
mImagePixWidth, mImagePixHeight, mImagePixDepth);
MTPI(" mParent: %08X mAssociationType: %04X mAssociationDesc: %04X\n",
mParent, mAssociationType, mAssociationDesc);
MTPI(" mSequenceNumber: %d mDateCreated: %ld mDateModified: %ld mKeywords: %s\n",
mSequenceNumber, mDateCreated, mDateModified, mKeywords);
}
+60
View File
@@ -0,0 +1,60 @@
/*
* 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++
*/
#ifndef _MTP_OBJECT_INFO_H
#define _MTP_OBJECT_INFO_H
#include "MtpTypes.h"
class MtpDataPacket;
class MtpObjectInfo {
public:
MtpObjectHandle mHandle;
MtpStorageID mStorageID;
MtpObjectFormat mFormat;
uint16_t mProtectionStatus;
uint32_t mCompressedSize;
MtpObjectFormat mThumbFormat;
uint32_t mThumbCompressedSize;
uint32_t mThumbPixWidth;
uint32_t mThumbPixHeight;
uint32_t mImagePixWidth;
uint32_t mImagePixHeight;
uint32_t mImagePixDepth;
MtpObjectHandle mParent;
uint16_t mAssociationType;
uint32_t mAssociationDesc;
uint32_t mSequenceNumber;
char* mName;
time_t mDateCreated;
time_t mDateModified;
char* mKeywords;
public:
MtpObjectInfo(MtpObjectHandle handle);
virtual ~MtpObjectInfo();
void read(MtpDataPacket& packet);
void print();
};
#endif // _MTP_OBJECT_INFO_H
+164
View File
@@ -0,0 +1,164 @@
/*
* 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 "MtpDebug.h"
#include "MtpPacket.h"
#include "mtp.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <usbhost/usbhost.h>
MtpPacket::MtpPacket(int bufferSize)
: mBuffer(NULL),
mBufferSize(bufferSize),
mAllocationIncrement(bufferSize),
mPacketSize(0)
{
mBuffer = (uint8_t *)malloc(bufferSize);
if (!mBuffer) {
MTPE("out of memory!");
abort();
}
}
MtpPacket::~MtpPacket() {
if (mBuffer)
free(mBuffer);
}
void MtpPacket::reset() {
allocate(MTP_CONTAINER_HEADER_SIZE);
mPacketSize = MTP_CONTAINER_HEADER_SIZE;
memset(mBuffer, 0, mBufferSize);
}
void MtpPacket::allocate(int length) {
if (length > mBufferSize) {
int newLength = length + mAllocationIncrement;
mBuffer = (uint8_t *)realloc(mBuffer, newLength);
if (!mBuffer) {
MTPE("out of memory!");
abort();
}
mBufferSize = newLength;
}
}
void MtpPacket::dump() {
#define DUMP_BYTES_PER_ROW 16
char buffer[500];
char* bufptr = buffer;
for (size_t i = 0; i < mPacketSize; i++) {
sprintf(bufptr, "%02X ", mBuffer[i]);
bufptr += strlen(bufptr);
if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
MTPD("%s", buffer);
bufptr = buffer;
}
}
if (bufptr != buffer) {
// print last line
MTPD("%s", buffer);
}
MTPD("\n");
}
void MtpPacket::copyFrom(const MtpPacket& src) {
int length = src.mPacketSize;
allocate(length);
mPacketSize = length;
memcpy(mBuffer, src.mBuffer, length);
}
uint16_t MtpPacket::getUInt16(int offset) const {
return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
}
uint32_t MtpPacket::getUInt32(int offset) const {
return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
}
void MtpPacket::putUInt16(int offset, uint16_t value) {
mBuffer[offset++] = (uint8_t)(value & 0xFF);
mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
}
void MtpPacket::putUInt32(int offset, uint32_t value) {
mBuffer[offset++] = (uint8_t)(value & 0xFF);
mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
}
uint16_t MtpPacket::getContainerCode() const {
return getUInt16(MTP_CONTAINER_CODE_OFFSET);
}
void MtpPacket::setContainerCode(uint16_t code) {
putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
}
uint16_t MtpPacket::getContainerType() const {
return getUInt16(MTP_CONTAINER_TYPE_OFFSET);
}
MtpTransactionID MtpPacket::getTransactionID() const {
return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET);
}
void MtpPacket::setTransactionID(MtpTransactionID id) {
putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
}
uint32_t MtpPacket::getParameter(int index) const {
if (index < 1 || index > 5) {
MTPE("index %d out of range in MtpPacket::getParameter", index);
return 0;
}
return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t));
}
void MtpPacket::setParameter(int index, uint32_t value) {
if (index < 1 || index > 5) {
MTPE("index %d out of range in MtpPacket::setParameter", index);
return;
}
int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t);
if (mPacketSize < offset + sizeof(uint32_t))
mPacketSize = offset + sizeof(uint32_t);
putUInt32(offset, value);
}
#ifdef MTP_HOST
int MtpPacket::transfer(struct usb_request* request) {
int result = usb_device_bulk_transfer(request->dev,
request->endpoint,
request->buffer,
request->buffer_length,
0);
request->actual_length = result;
return result;
}
#endif
+72
View File
@@ -0,0 +1,72 @@
/*
* 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++
*/
#ifndef _MTP_PACKET_H
#define _MTP_PACKET_H
#include "MtpTypes.h"
struct usb_request;
class MtpPacket {
protected:
uint8_t* mBuffer;
// current size of the buffer
int mBufferSize;
// number of bytes to add when resizing the buffer
int mAllocationIncrement;
// size of the data in the packet
unsigned mPacketSize;
public:
MtpPacket(int bufferSize);
virtual ~MtpPacket();
// sets packet size to the default container size and sets buffer to zero
virtual void reset();
void allocate(int length);
void dump();
void copyFrom(const MtpPacket& src);
uint16_t getContainerCode() const;
void setContainerCode(uint16_t code);
uint16_t getContainerType() const;
MtpTransactionID getTransactionID() const;
void setTransactionID(MtpTransactionID id);
uint32_t getParameter(int index) const;
void setParameter(int index, uint32_t value);
#ifdef MTP_HOST
int transfer(struct usb_request* request);
#endif
protected:
uint16_t getUInt16(int offset) const;
uint32_t getUInt32(int offset) const;
void putUInt16(int offset, uint16_t value);
void putUInt32(int offset, uint32_t value);
};
#endif // _MTP_PACKET_H
+531
View File
@@ -0,0 +1,531 @@
/*
* 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 "MtpDataPacket.h"
#include "MtpDebug.h"
#include "MtpProperty.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
MtpProperty::MtpProperty()
: mCode(0),
mType(0),
mWriteable(false),
mDefaultArrayLength(0),
mDefaultArrayValues(NULL),
mCurrentArrayLength(0),
mCurrentArrayValues(NULL),
mGroupCode(0),
mFormFlag(kFormNone),
mEnumLength(0),
mEnumValues(NULL)
{
memset(&mDefaultValue, 0, sizeof(mDefaultValue));
memset(&mCurrentValue, 0, sizeof(mCurrentValue));
memset(&mMinimumValue, 0, sizeof(mMinimumValue));
memset(&mMaximumValue, 0, sizeof(mMaximumValue));
}
MtpProperty::MtpProperty(MtpPropertyCode propCode,
MtpDataType type,
bool writeable,
int defaultValue)
: mCode(propCode),
mType(type),
mWriteable(writeable),
mDefaultArrayLength(0),
mDefaultArrayValues(NULL),
mCurrentArrayLength(0),
mCurrentArrayValues(NULL),
mGroupCode(0),
mFormFlag(kFormNone),
mEnumLength(0),
mEnumValues(NULL)
{
memset(&mDefaultValue, 0, sizeof(mDefaultValue));
memset(&mCurrentValue, 0, sizeof(mCurrentValue));
memset(&mMinimumValue, 0, sizeof(mMinimumValue));
memset(&mMaximumValue, 0, sizeof(mMaximumValue));
if (defaultValue) {
switch (type) {
case MTP_TYPE_INT8:
mDefaultValue.u.i8 = defaultValue;
break;
case MTP_TYPE_UINT8:
mDefaultValue.u.u8 = defaultValue;
break;
case MTP_TYPE_INT16:
mDefaultValue.u.i16 = defaultValue;
break;
case MTP_TYPE_UINT16:
mDefaultValue.u.u16 = defaultValue;
break;
case MTP_TYPE_INT32:
mDefaultValue.u.i32 = defaultValue;
break;
case MTP_TYPE_UINT32:
mDefaultValue.u.u32 = defaultValue;
break;
case MTP_TYPE_INT64:
mDefaultValue.u.i64 = defaultValue;
break;
case MTP_TYPE_UINT64:
mDefaultValue.u.u64 = defaultValue;
break;
default:
MTPE("unknown type %04X in MtpProperty::MtpProperty", type);
}
}
}
MtpProperty::~MtpProperty() {
if (mType == MTP_TYPE_STR) {
// free all strings
free(mDefaultValue.str);
free(mCurrentValue.str);
free(mMinimumValue.str);
free(mMaximumValue.str);
if (mDefaultArrayValues) {
for (int i = 0; i < mDefaultArrayLength; i++)
free(mDefaultArrayValues[i].str);
}
if (mCurrentArrayValues) {
for (int i = 0; i < mCurrentArrayLength; i++)
free(mCurrentArrayValues[i].str);
}
if (mEnumValues) {
for (int i = 0; i < mEnumLength; i++)
free(mEnumValues[i].str);
}
}
delete[] mDefaultArrayValues;
delete[] mCurrentArrayValues;
delete[] mEnumValues;
}
void MtpProperty::read(MtpDataPacket& packet) {
mCode = packet.getUInt16();
bool deviceProp = isDeviceProperty();
mType = packet.getUInt16();
mWriteable = (packet.getUInt8() == 1);
switch (mType) {
case MTP_TYPE_AINT8:
case MTP_TYPE_AUINT8:
case MTP_TYPE_AINT16:
case MTP_TYPE_AUINT16:
case MTP_TYPE_AINT32:
case MTP_TYPE_AUINT32:
case MTP_TYPE_AINT64:
case MTP_TYPE_AUINT64:
case MTP_TYPE_AINT128:
case MTP_TYPE_AUINT128:
mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
if (deviceProp)
mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
break;
default:
readValue(packet, mDefaultValue);
if (deviceProp)
readValue(packet, mCurrentValue);
}
if (!deviceProp)
mGroupCode = packet.getUInt32();
mFormFlag = packet.getUInt8();
if (mFormFlag == kFormRange) {
readValue(packet, mMinimumValue);
readValue(packet, mMaximumValue);
readValue(packet, mStepSize);
} else if (mFormFlag == kFormEnum) {
mEnumLength = packet.getUInt16();
mEnumValues = new MtpPropertyValue[mEnumLength];
for (int i = 0; i < mEnumLength; i++)
readValue(packet, mEnumValues[i]);
}
}
void MtpProperty::write(MtpDataPacket& packet) {
bool deviceProp = isDeviceProperty();
packet.putUInt16(mCode);
packet.putUInt16(mType);
packet.putUInt8(mWriteable ? 1 : 0);
switch (mType) {
case MTP_TYPE_AINT8:
case MTP_TYPE_AUINT8:
case MTP_TYPE_AINT16:
case MTP_TYPE_AUINT16:
case MTP_TYPE_AINT32:
case MTP_TYPE_AUINT32:
case MTP_TYPE_AINT64:
case MTP_TYPE_AUINT64:
case MTP_TYPE_AINT128:
case MTP_TYPE_AUINT128:
writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
if (deviceProp)
writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength);
break;
default:
writeValue(packet, mDefaultValue);
if (deviceProp)
writeValue(packet, mCurrentValue);
}
packet.putUInt32(mGroupCode);
if (!deviceProp)
packet.putUInt8(mFormFlag);
if (mFormFlag == kFormRange) {
writeValue(packet, mMinimumValue);
writeValue(packet, mMaximumValue);
writeValue(packet, mStepSize);
} else if (mFormFlag == kFormEnum) {
packet.putUInt16(mEnumLength);
for (int i = 0; i < mEnumLength; i++)
writeValue(packet, mEnumValues[i]);
}
}
void MtpProperty::setDefaultValue(const uint16_t* string) {
free(mDefaultValue.str);
if (string) {
MtpStringBuffer buffer(string);
mDefaultValue.str = strdup(buffer);
}
else
mDefaultValue.str = NULL;
}
void MtpProperty::setCurrentValue(const uint16_t* string) {
free(mCurrentValue.str);
if (string) {
MtpStringBuffer buffer(string);
mCurrentValue.str = strdup(buffer);
}
else
mCurrentValue.str = NULL;
}
void MtpProperty::setFormRange(int min, int max, int step) {
mFormFlag = kFormRange;
switch (mType) {
case MTP_TYPE_INT8:
mMinimumValue.u.i8 = min;
mMaximumValue.u.i8 = max;
mStepSize.u.i8 = step;
break;
case MTP_TYPE_UINT8:
mMinimumValue.u.u8 = min;
mMaximumValue.u.u8 = max;
mStepSize.u.u8 = step;
break;
case MTP_TYPE_INT16:
mMinimumValue.u.i16 = min;
mMaximumValue.u.i16 = max;
mStepSize.u.i16 = step;
break;
case MTP_TYPE_UINT16:
mMinimumValue.u.u16 = min;
mMaximumValue.u.u16 = max;
mStepSize.u.u16 = step;
break;
case MTP_TYPE_INT32:
mMinimumValue.u.i32 = min;
mMaximumValue.u.i32 = max;
mStepSize.u.i32 = step;
break;
case MTP_TYPE_UINT32:
mMinimumValue.u.u32 = min;
mMaximumValue.u.u32 = max;
mStepSize.u.u32 = step;
break;
case MTP_TYPE_INT64:
mMinimumValue.u.i64 = min;
mMaximumValue.u.i64 = max;
mStepSize.u.i64 = step;
break;
case MTP_TYPE_UINT64:
mMinimumValue.u.u64 = min;
mMaximumValue.u.u64 = max;
mStepSize.u.u64 = step;
break;
default:
MTPE("unsupported type for MtpProperty::setRange");
break;
}
}
void MtpProperty::setFormEnum(const int* values, int count) {
mFormFlag = kFormEnum;
delete[] mEnumValues;
mEnumValues = new MtpPropertyValue[count];
mEnumLength = count;
for (int i = 0; i < count; i++) {
int value = *values++;
switch (mType) {
case MTP_TYPE_INT8:
mEnumValues[i].u.i8 = value;
break;
case MTP_TYPE_UINT8:
mEnumValues[i].u.u8 = value;
break;
case MTP_TYPE_INT16:
mEnumValues[i].u.i16 = value;
break;
case MTP_TYPE_UINT16:
mEnumValues[i].u.u16 = value;
break;
case MTP_TYPE_INT32:
mEnumValues[i].u.i32 = value;
break;
case MTP_TYPE_UINT32:
mEnumValues[i].u.u32 = value;
break;
case MTP_TYPE_INT64:
mEnumValues[i].u.i64 = value;
break;
case MTP_TYPE_UINT64:
mEnumValues[i].u.u64 = value;
break;
default:
MTPE("unsupported type for MtpProperty::setEnum");
break;
}
}
}
void MtpProperty::setFormDateTime() {
mFormFlag = kFormDateTime;
}
void MtpProperty::print() {
MtpString buffer;
bool deviceProp = isDeviceProperty();
if (deviceProp)
MTPI(" %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
else
MTPI(" %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
MTPI(" type %04X", mType);
MTPI(" writeable %s", (mWriteable ? "true" : "false"));
buffer = " default value: ";
print(mDefaultValue, buffer);
MTPI("%s", (const char *)buffer);
if (deviceProp) {
buffer = " current value: ";
print(mCurrentValue, buffer);
MTPI("%s", (const char *)buffer);
}
switch (mFormFlag) {
case kFormNone:
break;
case kFormRange:
buffer = " Range (";
print(mMinimumValue, buffer);
buffer += ", ";
print(mMaximumValue, buffer);
buffer += ", ";
print(mStepSize, buffer);
buffer += ")";
MTPI("%s", (const char *)buffer);
break;
case kFormEnum:
buffer = " Enum { ";
for (int i = 0; i < mEnumLength; i++) {
print(mEnumValues[i], buffer);
buffer += " ";
}
buffer += "}";
MTPI("%s", (const char *)buffer);
break;
case kFormDateTime:
MTPI(" DateTime\n");
break;
default:
MTPI(" form %d\n", mFormFlag);
break;
}
}
void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
switch (mType) {
case MTP_TYPE_INT8:
buffer.appendFormat("%d", value.u.i8);
break;
case MTP_TYPE_UINT8:
buffer.appendFormat("%d", value.u.u8);
break;
case MTP_TYPE_INT16:
buffer.appendFormat("%d", value.u.i16);
break;
case MTP_TYPE_UINT16:
buffer.appendFormat("%d", value.u.u16);
break;
case MTP_TYPE_INT32:
buffer.appendFormat("%d", value.u.i32);
break;
case MTP_TYPE_UINT32:
buffer.appendFormat("%d", value.u.u32);
break;
case MTP_TYPE_INT64:
buffer.appendFormat("%lld", value.u.i64);
break;
case MTP_TYPE_UINT64:
buffer.appendFormat("%lld", value.u.u64);
break;
case MTP_TYPE_INT128:
buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
value.u.i128[2], value.u.i128[3]);
break;
case MTP_TYPE_UINT128:
buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
value.u.u128[2], value.u.u128[3]);
break;
case MTP_TYPE_STR:
buffer.appendFormat("%s", value.str);
break;
default:
MTPE("unsupported type for MtpProperty::print\n");
break;
}
}
void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
MtpStringBuffer stringBuffer;
switch (mType) {
case MTP_TYPE_INT8:
case MTP_TYPE_AINT8:
value.u.i8 = packet.getInt8();
break;
case MTP_TYPE_UINT8:
case MTP_TYPE_AUINT8:
value.u.u8 = packet.getUInt8();
break;
case MTP_TYPE_INT16:
case MTP_TYPE_AINT16:
value.u.i16 = packet.getInt16();
break;
case MTP_TYPE_UINT16:
case MTP_TYPE_AUINT16:
value.u.u16 = packet.getUInt16();
break;
case MTP_TYPE_INT32:
case MTP_TYPE_AINT32:
value.u.i32 = packet.getInt32();
break;
case MTP_TYPE_UINT32:
case MTP_TYPE_AUINT32:
value.u.u32 = packet.getUInt32();
break;
case MTP_TYPE_INT64:
case MTP_TYPE_AINT64:
value.u.i64 = packet.getInt64();
break;
case MTP_TYPE_UINT64:
case MTP_TYPE_AUINT64:
value.u.u64 = packet.getUInt64();
break;
case MTP_TYPE_INT128:
case MTP_TYPE_AINT128:
packet.getInt128(value.u.i128);
break;
case MTP_TYPE_UINT128:
case MTP_TYPE_AUINT128:
packet.getUInt128(value.u.u128);
break;
case MTP_TYPE_STR:
packet.getString(stringBuffer);
value.str = strdup(stringBuffer);
break;
default:
MTPE("unknown type %04X in MtpProperty::readValue", mType);
}
}
void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
MtpStringBuffer stringBuffer;
switch (mType) {
case MTP_TYPE_INT8:
case MTP_TYPE_AINT8:
packet.putInt8(value.u.i8);
break;
case MTP_TYPE_UINT8:
case MTP_TYPE_AUINT8:
packet.putUInt8(value.u.u8);
break;
case MTP_TYPE_INT16:
case MTP_TYPE_AINT16:
packet.putInt16(value.u.i16);
break;
case MTP_TYPE_UINT16:
case MTP_TYPE_AUINT16:
packet.putUInt16(value.u.u16);
break;
case MTP_TYPE_INT32:
case MTP_TYPE_AINT32:
packet.putInt32(value.u.i32);
break;
case MTP_TYPE_UINT32:
case MTP_TYPE_AUINT32:
packet.putUInt32(value.u.u32);
break;
case MTP_TYPE_INT64:
case MTP_TYPE_AINT64:
packet.putInt64(value.u.i64);
break;
case MTP_TYPE_UINT64:
case MTP_TYPE_AUINT64:
packet.putUInt64(value.u.u64);
break;
case MTP_TYPE_INT128:
case MTP_TYPE_AINT128:
packet.putInt128(value.u.i128);
break;
case MTP_TYPE_UINT128:
case MTP_TYPE_AUINT128:
packet.putUInt128(value.u.u128);
break;
case MTP_TYPE_STR:
if (value.str)
packet.putString(value.str);
else
packet.putEmptyString();
break;
default:
MTPE("unknown type %04X in MtpProperty::writeValue", mType);
}
}
MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
length = packet.getUInt32();
if (length == 0)
return NULL;
MtpPropertyValue* result = new MtpPropertyValue[length];
for (int i = 0; i < length; i++)
readValue(packet, result[i]);
return result;
}
void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
packet.putUInt32(length);
for (int i = 0; i < length; i++)
writeValue(packet, values[i]);
}
+114
View File
@@ -0,0 +1,114 @@
/*
* 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++
*/
#ifndef _MTP_PROPERTY_H
#define _MTP_PROPERTY_H
#include "MtpTypes.h"
class MtpDataPacket;
struct MtpPropertyValue {
union {
int8_t i8;
uint8_t u8;
int16_t i16;
uint16_t u16;
int32_t i32;
uint32_t u32;
int64_t i64;
uint64_t u64;
int128_t i128;
uint128_t u128;
} u;
// string in UTF8 format
char* str;
};
class MtpProperty {
public:
MtpPropertyCode mCode;
MtpDataType mType;
bool mWriteable;
MtpPropertyValue mDefaultValue;
MtpPropertyValue mCurrentValue;
// for array types
int mDefaultArrayLength;
MtpPropertyValue* mDefaultArrayValues;
int mCurrentArrayLength;
MtpPropertyValue* mCurrentArrayValues;
enum {
kFormNone = 0,
kFormRange = 1,
kFormEnum = 2,
kFormDateTime = 3,
};
uint32_t mGroupCode;
uint8_t mFormFlag;
// for range form
MtpPropertyValue mMinimumValue;
MtpPropertyValue mMaximumValue;
MtpPropertyValue mStepSize;
// for enum form
int mEnumLength;
MtpPropertyValue* mEnumValues;
public:
MtpProperty();
MtpProperty(MtpPropertyCode propCode,
MtpDataType type,
bool writeable = false,
int defaultValue = 0);
virtual ~MtpProperty();
inline MtpPropertyCode getPropertyCode() const { return mCode; }
void read(MtpDataPacket& packet);
void write(MtpDataPacket& packet);
void setDefaultValue(const uint16_t* string);
void setCurrentValue(const uint16_t* string);
void setFormRange(int min, int max, int step);
void setFormEnum(const int* values, int count);
void setFormDateTime();
void print();
void print(MtpPropertyValue& value, MtpString& buffer);
inline bool isDeviceProperty() const {
return ( ((mCode & 0xF000) == 0x5000)
|| ((mCode & 0xF800) == 0xD000));
}
private:
void readValue(MtpDataPacket& packet, MtpPropertyValue& value);
void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);
void writeArrayValues(MtpDataPacket& packet,
MtpPropertyValue* values, int length);
};
#endif // _MTP_PROPERTY_H
+61
View File
@@ -0,0 +1,61 @@
/*
* 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 <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include "MtpRequestPacket.h"
#include "MtpDebug.h"
#include <usbhost/usbhost.h>
MtpRequestPacket::MtpRequestPacket()
: MtpPacket(512)
{
}
MtpRequestPacket::~MtpRequestPacket() {
}
#ifdef MTP_DEVICE
int MtpRequestPacket::read(int fd) {
MTPD("block1 fd: %d\n", fd);
int ret = ::read(fd, mBuffer, mBufferSize);
MTPD("block2\n");
if (ret >= 0)
mPacketSize = ret;
else
mPacketSize = 0;
return ret;
}
#endif
#ifdef MTP_HOST
// write our buffer to the given endpoint (host mode)
int MtpRequestPacket::write(struct usb_request *request)
{
putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_COMMAND);
request->buffer = mBuffer;
request->buffer_length = mPacketSize;
return transfer(request);
}
#endif
+49
View File
@@ -0,0 +1,49 @@
/*
* 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++
*/
#ifndef _MTP_REQUEST_PACKET_H
#define _MTP_REQUEST_PACKET_H
#include "MtpPacket.h"
#include "mtp.h"
struct usb_request;
class MtpRequestPacket : public MtpPacket {
public:
MtpRequestPacket();
virtual ~MtpRequestPacket();
#ifdef MTP_DEVICE
// fill our buffer with data from the given file descriptor
int read(int fd);
#endif
#ifdef MTP_HOST
// write our buffer to the given endpoint
int write(struct usb_request *request);
#endif
inline MtpOperationCode getOperationCode() const { return getContainerCode(); }
inline void setOperationCode(MtpOperationCode code)
{ return setContainerCode(code); }
};
#endif // _MTP_REQUEST_PACKET_H
+58
View File
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use 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 <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include "MtpResponsePacket.h"
#include <usbhost/usbhost.h>
MtpResponsePacket::MtpResponsePacket()
: MtpPacket(512)
{
}
MtpResponsePacket::~MtpResponsePacket() {
}
#ifdef MTP_DEVICE
int MtpResponsePacket::write(int fd) {
putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize);
putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_RESPONSE);
int ret = ::write(fd, mBuffer, mPacketSize);
return (ret < 0 ? ret : 0);
}
#endif
#ifdef MTP_HOST
int MtpResponsePacket::read(struct usb_request *request) {
request->buffer = mBuffer;
request->buffer_length = mBufferSize;
int ret = transfer(request);
if (ret >= 0)
mPacketSize = ret;
else
mPacketSize = 0;
return ret;
}
#endif
+48
View File
@@ -0,0 +1,48 @@
/*
* 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++
*/
#ifndef _MTP_RESPONSE_PACKET_H
#define _MTP_RESPONSE_PACKET_H
#include "MtpPacket.h"
#include "mtp.h"
class MtpResponsePacket : public MtpPacket {
public:
MtpResponsePacket();
virtual ~MtpResponsePacket();
#ifdef MTP_DEVICE
// write our data to the given file descriptor
int write(int fd);
#endif
#ifdef MTP_HOST
// read our buffer with the given request
int read(struct usb_request *request);
#endif
inline MtpResponseCode getResponseCode() const { return getContainerCode(); }
inline void setResponseCode(MtpResponseCode code)
{ return setContainerCode(code); }
};
#endif // _MTP_RESPONSE_PACKET_H
+1337
View File
File diff suppressed because it is too large Load Diff
+155
View File
@@ -0,0 +1,155 @@
/*
* 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++
*/
#ifndef _MTP_SERVER_H
#define _MTP_SERVER_H
#include <utils/threads.h>
#include <utils/Vector.h>
#include "MtpRequestPacket.h"
#include "MtpDatabase.h"
#include "MtpDataPacket.h"
#include "MtpResponsePacket.h"
#include "MtpEventPacket.h"
#include "mtp.h"
#include "MtpUtils.h"
class MtpDatabase;
class MtpStorage;
class MtpServer {
private:
// file descriptor for MTP kernel driver
int mFD;
android::Mutex mMutex;
MtpDatabase* mDatabase;
// appear as a PTP device
bool mPtp;
// group to own new files and folders
int mFileGroup;
// permissions for new files and directories
int mFilePermission;
int mDirectoryPermission;
// current session ID
MtpSessionID mSessionID;
// true if we have an open session and mSessionID is valid
bool mSessionOpen;
MtpRequestPacket mRequest;
MtpDataPacket mData;
MtpResponsePacket mResponse;
MtpEventPacket mEvent;
MtpStorageList mStorages;
// handle for new object, set by SendObjectInfo and used by SendObject
MtpObjectHandle mSendObjectHandle;
MtpObjectFormat mSendObjectFormat;
MtpString mSendObjectFilePath;
size_t mSendObjectFileSize;
pthread_mutex_t mtpMutex;
// represents an MTP object that is being edited using the android extensions
// for direct editing (BeginEditObject, SendPartialObject, TruncateObject and EndEditObject)
class ObjectEdit {
public:
MtpObjectHandle mHandle;
MtpString mPath;
uint64_t mSize;
MtpObjectFormat mFormat;
int mFD;
ObjectEdit(MtpObjectHandle handle, const char* path, uint64_t size,
MtpObjectFormat format, int fd)
: mHandle(handle), mPath(path), mSize(size), mFormat(format), mFD(fd) {
}
virtual ~ObjectEdit() {
close(mFD);
}
};
android::Vector<ObjectEdit*> mObjectEditList;
public:
MtpServer(int fd, MtpDatabase* database, bool ptp,
int fileGroup, int filePerm, int directoryPerm);
virtual ~MtpServer();
MtpStorage* getStorage(MtpStorageID id);
inline bool hasStorage() { return mStorages.size() > 0; }
bool hasStorage(MtpStorageID id);
void addStorage(MtpStorage* storage);
void removeStorage(MtpStorage* storage);
void run();
void sendObjectAdded(MtpObjectHandle handle);
void sendObjectRemoved(MtpObjectHandle handle);
void sendObjectUpdated(MtpObjectHandle handle);
private:
void sendStoreAdded(MtpStorageID id);
void sendStoreRemoved(MtpStorageID id);
void sendEvent(MtpEventCode code, uint32_t param1);
void addEditObject(MtpObjectHandle handle, MtpString& path,
uint64_t size, MtpObjectFormat format, int fd);
ObjectEdit* getEditObject(MtpObjectHandle handle);
void removeEditObject(MtpObjectHandle handle);
void commitEdit(ObjectEdit* edit);
bool handleRequest();
MtpResponseCode doGetDeviceInfo();
MtpResponseCode doOpenSession();
MtpResponseCode doCloseSession();
MtpResponseCode doGetStorageIDs();
MtpResponseCode doGetStorageInfo();
MtpResponseCode doGetObjectPropsSupported();
MtpResponseCode doGetObjectHandles();
MtpResponseCode doGetNumObjects();
MtpResponseCode doGetObjectReferences();
MtpResponseCode doSetObjectReferences();
MtpResponseCode doGetObjectPropValue();
MtpResponseCode doSetObjectPropValue();
MtpResponseCode doGetDevicePropValue();
MtpResponseCode doSetDevicePropValue();
MtpResponseCode doResetDevicePropValue();
MtpResponseCode doGetObjectPropList();
MtpResponseCode doGetObjectInfo();
MtpResponseCode doGetObject();
MtpResponseCode doGetThumb();
MtpResponseCode doGetPartialObject(MtpOperationCode operation);
MtpResponseCode doSendObjectInfo();
MtpResponseCode doSendObject();
MtpResponseCode doDeleteObject();
MtpResponseCode doGetObjectPropDesc();
MtpResponseCode doGetDevicePropDesc();
MtpResponseCode doSendPartialObject();
MtpResponseCode doTruncateObject();
MtpResponseCode doBeginEditObject();
MtpResponseCode doEndEditObject();
};
#endif // _MTP_SERVER_H
+941
View File
@@ -0,0 +1,941 @@
/*
* 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 "MtpDebug.h"
#include "MtpStorage.h"
#include "MtpDataPacket.h"
#include "MtpServer.h"
#include "MtpEventPacket.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <sstream>
#define WATCH_FLAGS ( IN_CREATE | IN_DELETE | IN_MOVE | IN_MODIFY )
static int mtpid = 0;
MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
const char* description, uint64_t reserveSpace,
bool removable, uint64_t maxFileSize, MtpServer* refserver)
: mStorageID(id),
mFilePath(filePath),
mDescription(description),
mMaxCapacity(0),
mMaxFileSize(maxFileSize),
mReserveSpace(reserveSpace),
mRemovable(removable),
mServer(refserver)
{
MTPI("MtpStorage id: %d path: %s\n", id, filePath);
mtpparentid = 0;
inotify_thread = 0;
sendEvents = false;
use_mutex = true;
if (pthread_mutex_init(&mtpMutex, NULL) != 0) {
MTPE("Failed to init mtpMutex\n");
use_mutex = false;
}
if (pthread_mutex_init(&inMutex, NULL) != 0) {
MTPE("Failed to init inMutex\n");
use_mutex = false;
}
}
MtpStorage::~MtpStorage() {
if (inotify_thread) {
pthread_kill(inotify_thread, 0);
for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
inotify_rm_watch(inotify_fd, i->first);
}
close(inotify_fd);
}
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
delete i->second;
}
if (use_mutex) {
use_mutex = false;
pthread_mutex_destroy(&mtpMutex);
pthread_mutex_destroy(&inMutex);
}
}
int MtpStorage::getType() const {
return (mRemovable ? MTP_STORAGE_REMOVABLE_RAM : MTP_STORAGE_FIXED_RAM);
}
int MtpStorage::getFileSystemType() const {
return MTP_STORAGE_FILESYSTEM_HIERARCHICAL;
}
int MtpStorage::getAccessCapability() const {
return MTP_STORAGE_READ_WRITE;
}
uint64_t MtpStorage::getMaxCapacity() {
if (mMaxCapacity == 0) {
struct statfs stat;
if (statfs(getPath(), &stat))
return -1;
mMaxCapacity = (uint64_t)stat.f_blocks * (uint64_t)stat.f_bsize;
}
return mMaxCapacity;
}
uint64_t MtpStorage::getFreeSpace() {
struct statfs stat;
if (statfs(getPath(), &stat))
return -1;
uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
}
const char* MtpStorage::getDescription() const {
return (const char *)mDescription;
}
int MtpStorage::createDB() {
std::string mtpParent = "";
mtpstorageparent = getPath();
readParentDirs(getPath());
while (!mtpParentList.empty()) {
mtpParent = mtpParentList.front();
mtpParentList.pop_front();
readParentDirs(mtpParent);
}
MTPD("MtpStorage::createDB DONE\n");
if (use_mutex) {
MTPD("Starting inotify thread\n");
sendEvents = true;
inotify_thread = inotify();
} else {
MTPD("NOT starting inotify thread\n");
}
return 0;
}
MtpObjectHandleList* MtpStorage::getObjectList(MtpStorageID storageID, MtpObjectHandle parent) {
std::vector<int> mtpids;
int local_mtpparentid;
MTPD("MtpStorage::getObjectList\n");
MTPD("parent: %d\n", parent);
//append object id (numerical #s) of database to int array
MtpObjectHandleList* list = new MtpObjectHandleList();
if (parent == MTP_PARENT_ROOT) {
MTPD("parent == MTP_PARENT_ROOT\n");
local_mtpparentid = 1;
}
else {
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
MTPD("root: %d\n", i->second->Root());
Node* node = i->second->findNode(parent, i->second->Root());
if (node != NULL) {
local_mtpparentid = i->second->getMtpParentId(node);
MTPD("path: %s\n", i->second->getPath(node).c_str());
MTPD("mtpparentid: %d going to endloop\n", local_mtpparentid);
goto endloop;
}
}
}
MTPD("got to endloop\n");
endloop:
if (mtpmap[local_mtpparentid] == NULL) {
MTPD("mtpmap[mtpparentid] == NULL, returning\n");
return list;
}
MTPD("root: %d\n", mtpmap[local_mtpparentid]->Root());
mtpmap[local_mtpparentid]->getmtpids(mtpmap[local_mtpparentid]->Root(), &mtpids);
MTPD("here, mtpids->size(): %i\n", mtpids.size());
for (unsigned index = 0; index < mtpids.size(); index++) {
MTPD("mtpidhere[%i]: %d\n", index, mtpids.at(index));
list->push(mtpids.at(index));
}
return list;
}
int MtpStorage::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) {
struct stat st;
uint64_t size;
MTPD("MtpStorage::getObjectInfo handle: %d\n", handle);
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
Node* node = i->second->findNode(handle, i->second->Root());
MTPD("node returned: %d\n", node);
if (node != NULL) {
MTPD("found mtpid: %d\n", node->Mtpid());
info.mStorageID = getStorageID();
MTPD("info.mStorageID: %d\n", info.mStorageID);
info.mParent = node->getMtpParentId();
MTPD("mParent: %d\n", info.mParent);
lstat(node->getPath().c_str(), &st);
size = st.st_size;
MTPD("size is: %llu\n", size);
info.mCompressedSize = size;//(size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size);
info.mDateModified = st.st_mtime;
if (S_ISDIR(st.st_mode)) {
info.mFormat = MTP_FORMAT_ASSOCIATION;
}
else {
info.mFormat = MTP_FORMAT_UNDEFINED;
}
info.mName = strdup(basename(node->getPath().c_str()));
MTPD("MtpStorage::getObjectInfo found, Exiting getObjectInfo()\n");
return 0;
}
}
MTPE("MtpStorage::getObjectInfo no object found, error!\n");
return -1;
}
MtpObjectHandle MtpStorage::beginSendObject(const char* path,
MtpObjectFormat format,
MtpObjectHandle parent,
MtpStorageID storage,
uint64_t size,
time_t modified) {
MTPD("MtpStorage::beginSendObject(), path: '%s', parent: %d, storage: %d, format: %04x\n", path, parent, storage, format);
Node* node;
std::string parentdir;
std::string pathstr(path);
int parent_id;
parentdir = pathstr.substr(0, pathstr.find_last_of('/'));
MTPD("MtpStorage::beginSendObject() parentdir: %s\n", parentdir.c_str());
if (parentdir.compare(mtpstorageparent) == 0) {
// root directory
MTPD("MtpStorage::beginSendObject() root dir\n");
parent_id = 1;
++mtpid;
node = mtpmap[parent_id]->addNode(mtpid, path);
MTPD("node: %d\n", node);
node->addProperties(storage, 0);
if (format == MTP_FORMAT_ASSOCIATION) {
createEmptyDir(path);
}
return mtpid;
} else {
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
node = i->second->findNodePath(parentdir, i->second->Root());
if (node != NULL) {
MTPD("mtpid: %d\n", mtpid);
MTPD("path: %s\n", i->second->getPath(node).c_str());
parentdir = i->second->getPath(node);
parent = i->second->getMtpParentId(node);
if (parent == 0) {
MTPD("MtpStorage::beginSendObject parent is 0, error.\n");
return -1;
} else {
++mtpid;
node = mtpmap[parent]->addNode(mtpid, path);
node->addProperties(getStorageID(), getParentObject(parentdir));
for (iter i2 = mtpmap.begin(); i2 != mtpmap.end(); i2++) {
node = i2->second->findNodePath(path, i2->second->Root());
if (node != NULL) {
i2->second->setMtpParentId(parent, node);
}
}
if (format == MTP_FORMAT_ASSOCIATION) {
createEmptyDir(path);
}
}
return mtpid;
}
}
}
MTPE("MtpStorage::beginSendObject(), path: '%s', parent: %d, storage: %d, format: %04x\n", path, parent, storage, format);
return -1;
}
int MtpStorage::getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat) {
struct stat st;
Node* node;
MTPD("MtpStorage::getObjectFilePath handle: %i\n", handle);
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("handle: %d\n", handle);
node = i->second->findNode(handle, i->second->Root());
MTPD("node returned: %d\n", node);
if (node != NULL) {
lstat(node->getPath().c_str(), &st);
outFileLength = st.st_size;
outFilePath = strdup(node->getPath().c_str());
MTPD("outFilePath: %s\n", node->getPath().c_str());
goto end;
}
}
MTPE("MtpStorage::getObjectFilePath fauled to find handle: %i\n", handle);
return -1;
end:
outFormat = MTP_FORMAT_ASSOCIATION;
return 0;
}
int MtpStorage::readParentDirs(std::string path) {
struct dirent *de;
struct stat st;
DIR *d;
std::string parent, item, prevparent = "";
Node* node;
int storageID = getStorageID();
d = opendir(path.c_str());
MTPD("opening '%s'\n", path.c_str());
if (d == NULL) {
MTPD("error opening '%s' -- error: %s\n", path.c_str(), strerror(errno));
closedir(d);
}
while ((de = readdir(d)) != NULL) {
if (de->d_type == DT_DIR && strcmp(de->d_name, ".") == 0)
continue;
if (de->d_type == DT_DIR && strcmp(de->d_name, "..") != 0) {
// Handle dirs
item = path + "/" + de->d_name;
MTPD("dir: %s\n", item.c_str());
mtpParentList.push_back(item);
parent = item.substr(0, item.find_last_of('/'));
++mtpid;
MTPD("parent: %s\n", parent.c_str());
MTPD("mtpid: %d\n", mtpid);
if (prevparent != parent) {
mtpparentid++;
MTPD("Handle dirs, prevparent != parent, mtpparentid: %d\n", mtpparentid);
mtpmap[mtpparentid] = new Tree();
MTPD("prevparent addNode\n");
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(parent, i->second->Root());
if (node != NULL) {
i->second->setMtpParentId(mtpparentid, node);
}
}
node = mtpmap[mtpparentid]->addNode(mtpid, item);
node->addProperties(storageID, getParentObject(path));
if (sendEvents)
mServer->sendObjectAdded(mtpid);
}
else {
MTPD("add node\n");
mtpmap[mtpparentid]->addNode(mtpid, item);
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(item, i->second->Root());
if (node != NULL) {
i->second->setMtpParentId(mtpparentid, node);
node->addProperties(storageID, getParentObject(path));
}
}
if (sendEvents)
mServer->sendObjectAdded(mtpid);
}
prevparent = parent;
}
else {
if (strcmp(de->d_name, "..") != 0) {
// Handle files
item = path + "/" + de->d_name;
MTPD("file: %s\n", item.c_str());
parent = item.substr(0, item.find_last_of('/'));
MTPD("parent: %s\n", parent.c_str());
++mtpid;
MTPD("mtpid: %d\n", mtpid);
if (prevparent != parent) {
mtpparentid++;
MTPD("mtpparentid1: %d\n", mtpparentid);
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(path, i->second->Root());
if (node != NULL) {
i->second->setMtpParentId(mtpparentid, node);
node->addProperties(storageID, getParentObject(path));
}
}
}
if (mtpmap[mtpparentid] == NULL) {
mtpmap[mtpparentid] = new Tree();
}
MTPD("blank addNode\n");
node = mtpmap[mtpparentid]->addNode(mtpid, item);
node->addProperties(storageID, getParentObject(path));
prevparent = parent;
if (sendEvents)
mServer->sendObjectAdded(mtpid);
}
else {
// Handle empty dirs?
MTPD("checking for empty dir '%s'\n", path.c_str());
int count = 0;
DIR *dirc;
struct dirent *ep;
dirc = opendir(path.c_str());
if (dirc != NULL) {
while ((ep = readdir(dirc)))
++count;
MTPD("count: %d\n", count);
closedir(dirc);
}
if (count == 2) {
MTPD("'%s' is an empty dir\n", path.c_str());
createEmptyDir(path.c_str());
goto end;
}
}
}
}
end:
closedir(d);
return 0;
}
void MtpStorage::deleteTrees(int parent) {
Node* node = mtpmap[parent]->Root();
MTPD("MtpStorage::deleteTrees deleting %i\n", parent);
while (node != NULL) {
if (node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT) == MTP_FORMAT_ASSOCIATION) {
deleteTrees(node->getMtpParentId());
}
node = mtpmap[parent]->getNext(node);
}
delete mtpmap[parent];
mtpmap.erase(parent);
MTPD("MtpStorage::deleteTrees deleted %i\n", parent);
}
int MtpStorage::deleteFile(MtpObjectHandle handle) {
int local_parent_id = 0;
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("MtpStorage::deleteFile handle: %d\n", handle);
Node* node = i->second->findNode(handle, i->second->Root());
MTPD("MtpStorage::deleteFile node returned: %d\n", node);
if (node != NULL) {
if (node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT) == MTP_FORMAT_ASSOCIATION) {
local_parent_id = node->getMtpParentId();
}
MTPD("deleting handle: %d\n", handle);
i->second->deleteNode(handle);
MTPD("deleted\n");
goto end;
}
}
MTPE("MtpStorage::deleteFile deleting handle: %d FAILED\n", handle);
return -1;
end:
if (local_parent_id) {
deleteTrees(local_parent_id);
}
return 0;
}
int MtpStorage::getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet) {
Node *n;
int local_mtpid = 0;
int local_mtpparentid = 0;
std::vector<int> propertyCodes;
std::vector<int> dataTypes;
std::vector<std::string> valueStrs;
std::vector<int> longValues;
int count = 0;
MTPD("MtpStorage::getObjectPropertyList handle: %d, format: %d, property: %lx\n", handle, format, property);
if (property == MTP_PROPERTY_OBJECT_FORMAT) {
MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_OBJECT_FORMAT\n");
MTPD("mtpmap count: %d\n", mtpmap.size());
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node *node = i->second->findNode(handle, i->second->Root());
MTPD("index: %d\n", index);
MTPD("node: %d\n", node);
if (node != NULL) {
uint64_t longval = node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT);
local_mtpparentid = i->second->getMtpParentId(node);
MTPD("object format longValue: %llu\n", longval);
propertyCodes.push_back(MTP_PROPERTY_OBJECT_FORMAT);
longValues.push_back(node->getIntProperty(MTP_PROPERTY_OBJECT_FORMAT));
valueStrs.push_back("");
dataTypes.push_back(4);
count = 1;
local_mtpid = node->Mtpid();
goto endloop;
}
}
}
else if (property == MTP_PROPERTY_STORAGE_ID) {
MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_STORAGE_ID\n");
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node *node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
propertyCodes.push_back(MTP_PROPERTY_STORAGE_ID);
longValues.push_back(getStorageID());
valueStrs.push_back("");
dataTypes.push_back(4);
count = 1;
local_mtpid = node->Mtpid();
goto endloop;
}
}
}
else if (property == MTP_PARENT_ROOT) {
MTPD("MtpStorage::getObjectPropertyList MTP_PARENT_ROOT\n");
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node* node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
local_mtpparentid = i->second->getMtpParentId(node);
MTPD("path: %s\n", i->second->getPath(node).c_str());
MTPD("mtpparentid: %d going to endloop\n", local_mtpparentid);
std::vector<Node::mtpProperty> mtpprop = node->getMtpProps();
count = mtpprop.size();
for (int i = 0; i < count; ++i) {
propertyCodes.push_back(mtpprop[i].property);
longValues.push_back(mtpprop[i].valueInt);
valueStrs.push_back(mtpprop[i].valueStr);
dataTypes.push_back(mtpprop[i].dataType);
}
local_mtpid = node->Mtpid();
goto endloop;
}
}
}
else if (property == MTP_PROPERTY_PROTECTION_STATUS) {
MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_PROTECTION_STATUS\n");
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node *node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
propertyCodes.push_back(MTP_PROPERTY_PROTECTION_STATUS);
longValues.push_back(0);
valueStrs.push_back("");
dataTypes.push_back(8);
count = 1;
local_mtpid = node->Mtpid();
goto endloop;
}
}
}
else if (property == MTP_PROPERTY_OBJECT_SIZE) {
MTPD("MtpStorage::getObjectPropertyList MTP_PROPERTY_OBJECT_SIZE\n");
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node *node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
struct stat st;
uint64_t size;
lstat(node->getPath().c_str(), &st);
size = st.st_size;
propertyCodes.push_back(MTP_PROPERTY_OBJECT_SIZE);
longValues.push_back(size);
valueStrs.push_back("");
dataTypes.push_back(8);
count = 1;
local_mtpid = node->Mtpid();
goto endloop;
}
}
}
else {
MTPE("MtpStorage::getObjectPropertyList unsupported property %x\n", property);
return -1;
}
endloop:
MTPD("mtpparentid: %d\n", local_mtpparentid);
MTPD("count: %d\n", count);
packet.putUInt32(count);
if (count > 0) {
std::string stringValuesArray;
for (int i = 0; i < count; ++i) {
packet.putUInt32(local_mtpid);
packet.putUInt16(propertyCodes[i]);
MTPD("dataTypes: %d\n", dataTypes[i]);
packet.putUInt16(dataTypes[i]);
MTPD("propertyCode: %s\n", MtpDebug::getObjectPropCodeName(propertyCodes[i]));
MTPD("longValues: %d\n", longValues[i]);
switch (dataTypes[i]) {
case MTP_TYPE_INT8:
MTPD("MTP_TYPE_INT8\n");
packet.putInt8(longValues[i]);
break;
case MTP_TYPE_UINT8:
MTPD("MTP_TYPE_UINT8\n");
packet.putUInt8(longValues[i]);
break;
case MTP_TYPE_INT16:
MTPD("MTP_TYPE_INT16\n");
packet.putInt16(longValues[i]);
break;
case MTP_TYPE_UINT16:
MTPD("MTP_TYPE_UINT16\n");
packet.putUInt16(longValues[i]);
break;
case MTP_TYPE_INT32:
MTPD("MTP_TYPE_INT32\n");
packet.putInt32(longValues[i]);
break;
case MTP_TYPE_UINT32:
MTPD("MTP_TYPE_UINT32\n");
packet.putUInt32(longValues[i]);
break;
case MTP_TYPE_INT64:
MTPD("MTP_TYPE_INT64\n");
packet.putInt64(longValues[i]);
break;
case MTP_TYPE_UINT64:
MTPD("MTP_TYPE_UINT64\n");
packet.putUInt64(longValues[i]);
break;
case MTP_TYPE_INT128:
MTPD("MTP_TYPE_INT128\n");
packet.putInt128(longValues[i]);
break;
case MTP_TYPE_UINT128:
MTPD("MTP_TYPE_UINT128\n");
packet.putUInt128(longValues[i]);
break;
case MTP_TYPE_STR:
MTPD("MTP_TYPE_STR: %s\n", valueStrs[i].c_str());
packet.putString((const char*) valueStrs[i].c_str());
break;
default:
MTPE("bad or unsupported data type: %i in MyMtpDatabase::getObjectPropertyList", dataTypes[i]);
break;
}
}
}
return 0;
}
int MtpStorage::renameObject(MtpObjectHandle handle, std::string newName) {
int index;
MTPD("MtpStorage::renameObject, handle: %d, new name: '%s'\n", handle, newName.c_str());
if (handle == MTP_PARENT_ROOT) {
MTPE("parent == MTP_PARENT_ROOT, cannot rename root\n");
return -1;
} else {
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
MTPD("root: %d\n", i->second->Root());
Node* node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
std::string oldName = i->second->getPath(node);
std::string parentdir = oldName.substr(0, oldName.find_last_of('/'));
std::string newFullName = parentdir + "/" + newName;
MTPD("old: '%s', new: '%s'\n", oldName.c_str(), newFullName.c_str());
if (rename(oldName.c_str(), newFullName.c_str()) == 0) {
node->setPath(newFullName);
return 0;
} else {
MTPE("MtpStorage::renameObject failed, handle: %d, new name: '%s'\n", handle, newName.c_str());
return -1;
}
}
}
}
MTPE("MtpStorage::renameObject handle / node not found, error!\n");
return -1;
}
void MtpStorage::createEmptyDir(const char* path) {
Node *node;
++mtpparentid;
MtpStorageID storage = getStorageID();
MTPD("MtpStorage::createEmptyDir path: '%s', storage: %i, mtpparentid: %d\n", path, storage, mtpparentid);
mtpmap[mtpparentid] = new Tree();
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(path, i->second->Root());
if (node != NULL) {
mtpmap[mtpparentid]->setMtpParentId(mtpparentid, node);
}
}
}
int MtpStorage::getObjectPropertyValue(MtpObjectHandle handle, MtpObjectProperty property, uint64_t &longValue) {
Node *node;
for (iter i = mtpmap.begin(); i != mtpmap.end(); i++) {
node = i->second->findNode(handle, i->second->Root());
if (node != NULL) {
longValue = node->getIntProperty(property);
return 0;
}
}
MTPE("MtpStorage::getObjectPropertyValue unable to locate handle: %i\n", handle);
return -1;
}
pthread_t MtpStorage::inotify(void) {
pthread_t thread;
ThreadPtr inotifyptr = &MtpStorage::inotify_t;
PThreadPtr p = *(PThreadPtr*)&inotifyptr;
pthread_create(&thread, NULL, p, this);
return thread;
}
int MtpStorage::addInotifyDirs(std::string path) {
struct dirent *de;
DIR *d;
struct stat st;
std::string inotifypath;
d = opendir(path.c_str());
if (d == NULL) {
MTPE("MtpStorage::addInotifyDirs unable to open '%s'\n", path.c_str());
closedir(d);
return -1;
}
while ((de = readdir(d)) != NULL) {
if (de->d_type != DT_DIR || strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
inotifypath = path + "/" + de->d_name;
if (addInotifyDirs(inotifypath)) {
closedir(d);
return -1;
}
inotify_wd = inotify_add_watch(inotify_fd, inotifypath.c_str(), IN_CREATE | IN_DELETE);
inotifymap[inotify_wd] = inotifypath;
MTPD("added inotify dir: '%s'\n", inotifypath.c_str());
}
closedir(d);
return 0;
}
int MtpStorage::inotify_t(void) {
int len, i = 0;
int local_mtpparentid;
Node* node = NULL;
struct stat st;
#define EVENT_SIZE ( sizeof(struct inotify_event) )
#define EVENT_BUF_LEN ( 1024 * ( EVENT_SIZE + 16) )
char buf[EVENT_BUF_LEN];
std::string item, parent = "";
MTPD("starting inotify thread\n");
inotify_fd = inotify_init();
if (inotify_fd < 0){
MTPE("Can't run inotify for mtp server\n");
}
inotify_wd = inotify_add_watch(inotify_fd, getPath(), WATCH_FLAGS);
inotifymap[inotify_wd] = getPath();
if (addInotifyDirs(getPath())) {
MTPE("MtpStorage::inotify_t failed to add watches to directories\n");
for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
inotify_rm_watch(inotify_fd, i->first);
}
close(inotify_fd);
return -1;
}
while (true) {
i = 0;
len = read(inotify_fd, buf, EVENT_BUF_LEN);
if (len < 0) {
MTPE("inotify_t Can't read inotify events\n");
}
while (i < len) {
struct inotify_event *event = ( struct inotify_event * ) &buf[ i ];
if ( event->len ) {
if (inotifymap[event->wd].empty()) {
MTPE("Unable to locate inotify_wd: %i\n", event->wd);
goto end;
} else {
item = inotifymap[event->wd];
item = item + "/" + event->name;
MTPD("inotify_t item: '%s'\n", item.c_str());
if (event->mask & IN_CREATE || event->mask & IN_MOVED_TO) {
lockMutex(1);
if (event->mask & IN_ISDIR) {
MTPD("inotify_t create is dir\n");
} else {
MTPD("inotify_t create is file\n");
}
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(item, i->second->Root());
if (node != NULL)
break;
}
if (node == NULL) {
parent = item.substr(0, item.find_last_of('/'));
MTPD("parent: %s\n", parent.c_str());
if (parent == getPath()) {
local_mtpparentid = 1;
} else {
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(parent, i->second->Root());
MTPD("searching for node: %d\n", (int)node);
if (node != NULL) {
local_mtpparentid = i->second->getMtpParentId(node);
break;
}
}
if (node == NULL) {
MTPE("inotify_t unable to locate mtparentid\n");
goto end;
}
}
++mtpid;
MTPD("mtpid: %d\n", mtpid);
MTPD("mtpparentid1: %d\n", local_mtpparentid);
node = mtpmap[local_mtpparentid]->addNode(mtpid, item);
mtpmap[local_mtpparentid]->setMtpParentId(local_mtpparentid, node);
node->addProperties(getStorageID(), getParentObject(parent));
if (event->mask & IN_ISDIR) {
createEmptyDir(item.c_str());
}
mServer->sendObjectAdded(mtpid);
} else {
MTPD("inotify_t item already exists.\n");
}
if (event->mask & IN_ISDIR) {
inotify_wd = inotify_add_watch(inotify_fd, item.c_str(), WATCH_FLAGS);
inotifymap[inotify_wd] = item;
MTPD("added inotify dir: '%s'\n", item.c_str());
MTPD("inotify_t scanning new dir\n");
readParentDirs(item);
std::string mtpParent;
while (!mtpParentList.empty()) {
mtpParent = mtpParentList.front();
mtpParentList.pop_front();
readParentDirs(mtpParent);
inotify_wd = inotify_add_watch(inotify_fd, mtpParent.c_str(), WATCH_FLAGS);
inotifymap[inotify_wd] = mtpParent;
MTPD("added inotify dir: '%s'\n", mtpParent.c_str());
}
}
} else if (event->mask & IN_DELETE || event->mask & IN_MOVED_FROM) {
lockMutex(1);
if (event->mask & IN_ISDIR) {
MTPD("inotify_t Directory %s deleted\n", event->name);
} else {
MTPD("inotify_t File %s deleted\n", event->name);
}
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(item, i->second->Root());
if (node != NULL)
break;
}
if (node != NULL && node->Mtpid() > 0) {
int local_id = node->Mtpid();
node = NULL;
deleteFile(local_id);
mServer->sendObjectRemoved(local_id);
} else {
MTPD("inotify_t already removed.\n");
}
if (event->mask & IN_ISDIR) {
std::string orig_item = item + "/";
size_t item_size = orig_item.size();
std::string path_check;
for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
if ((i->second.size() > item_size && i->second.substr(0, item_size) == orig_item) || i->second == item) {
inotify_rm_watch(inotify_fd, i->first);
MTPD("inotify_t removing watch on '%s'\n", i->second.c_str());
inotifymap.erase(i->first);
}
}
}
} else if (event->mask & IN_MODIFY) {
MTPD("inotify_t item %s modified.\n", event->name);
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(item, i->second->Root());
if (node != NULL)
break;
}
if (node != NULL) {
uint64_t orig_size = node->getIntProperty(MTP_PROPERTY_OBJECT_SIZE);
struct stat st;
lstat(item.c_str(), &st);
uint64_t new_size = (uint64_t)st.st_size;
if (orig_size != new_size) {
MTPD("size changed from %llu to %llu on mtpid: %i\n", orig_size, new_size, node->Mtpid());
node->updateProperty(MTP_PROPERTY_OBJECT_SIZE, new_size, "", MTP_TYPE_UINT64);
mServer->sendObjectUpdated(node->Mtpid());
}
} else {
MTPE("inotify_t modified item not found\n");
}
}
}
}
end:
unlockMutex(1);
i += EVENT_SIZE + event->len;
}
}
for (std::map<int, std::string>::iterator i = inotifymap.begin(); i != inotifymap.end(); i++) {
inotify_rm_watch(inotify_fd, i->first);
}
close(inotify_fd);
return 0;
}
int MtpStorage::getParentObject(std::string parent_path) {
Node* node;
if (parent_path == getPath()) {
MTPD("MtpStorage::getParentObject for: '%s' returning: 0 for root\n", parent_path.c_str());
return 0;
}
for (iter i = mtpmap.begin(); i != mtpmap.end(); ++i) {
node = i->second->findNodePath(parent_path, i->second->Root());
if (node != NULL) {
MTPD("MtpStorage::getParentObject for: '%s' returning: %i\n", parent_path.c_str(), node->Mtpid());
return node->Mtpid();
}
}
MTPE("MtpStorage::getParentObject for: '%s' unable to locate node\n", parent_path.c_str());
return -1;
}
void MtpStorage::lockMutex(int thread_type) {
if (!use_mutex)
return; // mutex is disabled
if (thread_type) {
// inotify thread
pthread_mutex_lock(&inMutex);
while (pthread_mutex_trylock(&mtpMutex)) {
pthread_mutex_unlock(&inMutex);
usleep(32000);
pthread_mutex_lock(&inMutex);
}
} else {
// main mtp thread
pthread_mutex_lock(&mtpMutex);
while (pthread_mutex_trylock(&inMutex)) {
pthread_mutex_unlock(&mtpMutex);
usleep(13000);
pthread_mutex_lock(&mtpMutex);
}
}
}
void MtpStorage::unlockMutex(int thread_type) {
if (!use_mutex)
return; // mutex is disabled
pthread_mutex_unlock(&inMutex);
pthread_mutex_unlock(&mtpMutex);
}
+103
View File
@@ -0,0 +1,103 @@
/*
* 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++
*/
#ifndef _MTP_STORAGE_H
#define _MTP_STORAGE_H
#include "mtp.h"
#include "MtpObjectInfo.h"
#include <string>
#include <deque>
#include <map>
#include <libgen.h>
#include <pthread.h>
#include "btree.hpp"
#include "MtpServer.h"
class MtpDatabase;
class MtpStorage {
private:
MtpStorageID mStorageID;
MtpString mFilePath;
MtpString mDescription;
uint64_t mMaxCapacity;
uint64_t mMaxFileSize;
// amount of free space to leave unallocated
uint64_t mReserveSpace;
bool mRemovable;
MtpServer* mServer;
std::deque<std::string> mtpParentList;
int mtpparentid;
Tree *mtpdbtree;
typedef std::map<int, Tree*> maptree;
typedef maptree::iterator iter;
maptree mtpmap;
std::string mtpstorageparent;
pthread_t inotify_thread;
int inotify_fd;
int inotify_wd;
android::Mutex mMutex;
public:
MtpStorage(MtpStorageID id, const char* filePath,
const char* description, uint64_t reserveSpace,
bool removable, uint64_t maxFileSize, MtpServer* refserver);
virtual ~MtpStorage();
inline MtpStorageID getStorageID() const { return mStorageID; }
int getType() const;
int getFileSystemType() const;
int getAccessCapability() const;
uint64_t getMaxCapacity();
uint64_t getFreeSpace();
const char* getDescription() const;
inline const char* getPath() const { return (const char *)mFilePath; }
inline bool isRemovable() const { return mRemovable; }
inline uint64_t getMaxFileSize() const { return mMaxFileSize; }
int readParentDirs(std::string path);
int createDB();
MtpObjectHandleList* getObjectList(MtpStorageID storageID, MtpObjectHandle parent);
int getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info);
MtpObjectHandle beginSendObject(const char* path, MtpObjectFormat format, MtpObjectHandle parent, MtpStorageID storage, uint64_t size, time_t modified);
int getObjectPropertyList(MtpObjectHandle handle, uint32_t format, uint32_t property, int groupCode, int depth, MtpDataPacket& packet);
int getObjectFilePath(MtpObjectHandle handle, MtpString& outFilePath, int64_t& outFileLength, MtpObjectFormat& outFormat);
int deleteFile(MtpObjectHandle handle);
int renameObject(MtpObjectHandle handle, std::string newName);
int getObjectPropertyValue(MtpObjectHandle handle, MtpObjectProperty property, uint64_t &longValue);
void lockMutex(int thread_type);
void unlockMutex(int thread_type);
private:
void createEmptyDir(const char* path);
pthread_t inotify();
int inotify_t();
typedef int (MtpStorage::*ThreadPtr)(void);
typedef void* (*PThreadPtr)(void *);
std::map<int, std::string> inotifymap;
int addInotifyDirs(std::string path);
void deleteTrees(int parent);
bool sendEvents;
int getParentObject(std::string parent_path);
bool use_mutex;
pthread_mutex_t inMutex; // inotify mutex
pthread_mutex_t mtpMutex; // main mtp mutex
};
#endif // _MTP_STORAGE_H
+69
View File
@@ -0,0 +1,69 @@
/*
* 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 "MtpDebug.h"
#include "MtpDataPacket.h"
#include "MtpStorageInfo.h"
#include "MtpStringBuffer.h"
MtpStorageInfo::MtpStorageInfo(MtpStorageID id)
: mStorageID(id),
mStorageType(0),
mFileSystemType(0),
mAccessCapability(0),
mMaxCapacity(0),
mFreeSpaceBytes(0),
mFreeSpaceObjects(0),
mStorageDescription(NULL),
mVolumeIdentifier(NULL)
{
}
MtpStorageInfo::~MtpStorageInfo() {
if (mStorageDescription)
free(mStorageDescription);
if (mVolumeIdentifier)
free(mVolumeIdentifier);
}
void MtpStorageInfo::read(MtpDataPacket& packet) {
MtpStringBuffer string;
// read the device info
mStorageType = packet.getUInt16();
mFileSystemType = packet.getUInt16();
mAccessCapability = packet.getUInt16();
mMaxCapacity = packet.getUInt64();
mFreeSpaceBytes = packet.getUInt64();
mFreeSpaceObjects = packet.getUInt32();
packet.getString(string);
mStorageDescription = strdup((const char *)string);
packet.getString(string);
mVolumeIdentifier = strdup((const char *)string);
}
void MtpStorageInfo::print() {
MTPI("Storage Info %08X:\n\tmStorageType: %d\n\tmFileSystemType: %d\n\tmAccessCapability: %d\n",
mStorageID, mStorageType, mFileSystemType, mAccessCapability);
MTPI("\tmMaxCapacity: %lld\n\tmFreeSpaceBytes: %lld\n\tmFreeSpaceObjects: %d\n",
mMaxCapacity, mFreeSpaceBytes, mFreeSpaceObjects);
MTPI("\tmStorageDescription: %s\n\tmVolumeIdentifier: %s\n",
mStorageDescription, mVolumeIdentifier);
}
+49
View File
@@ -0,0 +1,49 @@
/*
* 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++
*/
#ifndef _MTP_STORAGE_INFO_H
#define _MTP_STORAGE_INFO_H
#include "MtpTypes.h"
class MtpDataPacket;
class MtpStorageInfo {
public:
MtpStorageID mStorageID;
uint16_t mStorageType;
uint16_t mFileSystemType;
uint16_t mAccessCapability;
uint64_t mMaxCapacity;
uint64_t mFreeSpaceBytes;
uint32_t mFreeSpaceObjects;
char* mStorageDescription;
char* mVolumeIdentifier;
public:
MtpStorageInfo(MtpStorageID id);
virtual ~MtpStorageInfo();
void read(MtpDataPacket& packet);
void print();
};
#endif // _MTP_STORAGE_INFO_H
+167
View File
@@ -0,0 +1,167 @@
/*
* 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 <string.h>
#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
MtpStringBuffer::MtpStringBuffer()
: mCharCount(0),
mByteCount(1)
{
mBuffer[0] = 0;
}
MtpStringBuffer::MtpStringBuffer(const char* src)
: mCharCount(0),
mByteCount(1)
{
set(src);
}
MtpStringBuffer::MtpStringBuffer(const uint16_t* src)
: mCharCount(0),
mByteCount(1)
{
set(src);
}
MtpStringBuffer::MtpStringBuffer(const MtpStringBuffer& src)
: mCharCount(src.mCharCount),
mByteCount(src.mByteCount)
{
memcpy(mBuffer, src.mBuffer, mByteCount);
}
MtpStringBuffer::~MtpStringBuffer() {
}
void MtpStringBuffer::set(const char* src) {
size_t length = strlen(src);
if (length >= sizeof(mBuffer))
length = sizeof(mBuffer) - 1;
memcpy(mBuffer, src, length);
// count the characters
int count = 0;
char ch;
while ((ch = *src++) != 0) {
if ((ch & 0x80) == 0) {
// single byte character
} else if ((ch & 0xE0) == 0xC0) {
// two byte character
if (! *src++) {
// last character was truncated, so ignore last byte
length--;
break;
}
} else if ((ch & 0xF0) == 0xE0) {
// 3 byte char
if (! *src++) {
// last character was truncated, so ignore last byte
length--;
break;
}
if (! *src++) {
// last character was truncated, so ignore last two bytes
length -= 2;
break;
}
}
count++;
}
mByteCount = length + 1;
mBuffer[length] = 0;
mCharCount = count;
}
void MtpStringBuffer::set(const uint16_t* src) {
int count = 0;
uint16_t ch;
uint8_t* dest = mBuffer;
while ((ch = *src++) != 0 && count < 255) {
if (ch >= 0x0800) {
*dest++ = (uint8_t)(0xE0 | (ch >> 12));
*dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
*dest++ = (uint8_t)(0x80 | (ch & 0x3F));
} else if (ch >= 0x80) {
*dest++ = (uint8_t)(0xC0 | (ch >> 6));
*dest++ = (uint8_t)(0x80 | (ch & 0x3F));
} else {
*dest++ = ch;
}
count++;
}
*dest++ = 0;
mCharCount = count;
mByteCount = dest - mBuffer;
}
void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
int count = packet->getUInt8();
uint8_t* dest = mBuffer;
for (int i = 0; i < count; i++) {
uint16_t ch = packet->getUInt16();
if (ch >= 0x0800) {
*dest++ = (uint8_t)(0xE0 | (ch >> 12));
*dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
*dest++ = (uint8_t)(0x80 | (ch & 0x3F));
} else if (ch >= 0x80) {
*dest++ = (uint8_t)(0xC0 | (ch >> 6));
*dest++ = (uint8_t)(0x80 | (ch & 0x3F));
} else {
*dest++ = ch;
}
}
*dest++ = 0;
mCharCount = count;
mByteCount = dest - mBuffer;
}
void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
int count = mCharCount;
const uint8_t* src = mBuffer;
packet->putUInt8(count > 0 ? count + 1 : 0);
// expand utf8 to 16 bit chars
for (int i = 0; i < count; i++) {
uint16_t ch;
uint16_t ch1 = *src++;
if ((ch1 & 0x80) == 0) {
// single byte character
ch = ch1;
} else if ((ch1 & 0xE0) == 0xC0) {
// two byte character
uint16_t ch2 = *src++;
ch = ((ch1 & 0x1F) << 6) | (ch2 & 0x3F);
} else {
// three byte character
uint16_t ch2 = *src++;
uint16_t ch3 = *src++;
ch = ((ch1 & 0x0F) << 12) | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
}
packet->putUInt16(ch);
}
// only terminate with zero if string is not empty
if (count > 0)
packet->putUInt16(0);
}
+55
View File
@@ -0,0 +1,55 @@
/*
* 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++
*/
#ifndef _MTP_STRING_BUFFER_H
#define _MTP_STRING_BUFFER_H
#include <stdint.h>
class MtpDataPacket;
// Represents a utf8 string, with a maximum of 255 characters
class MtpStringBuffer {
private:
// mBuffer contains string in UTF8 format
// maximum 3 bytes/character, with 1 extra for zero termination
uint8_t mBuffer[255 * 3 + 1];
int mCharCount;
int mByteCount;
public:
MtpStringBuffer();
MtpStringBuffer(const char* src);
MtpStringBuffer(const uint16_t* src);
MtpStringBuffer(const MtpStringBuffer& src);
virtual ~MtpStringBuffer();
void set(const char* src);
void set(const uint16_t* src);
void readFromPacket(MtpDataPacket* packet);
void writeToPacket(MtpDataPacket* packet) const;
inline int getCharCount() const { return mCharCount; }
inline int getByteCount() const { return mByteCount; }
inline operator const char*() const { return (const char *)mBuffer; }
};
#endif // _MTP_STRING_BUFFER_H
Executable
+78
View File
@@ -0,0 +1,78 @@
/*
* 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++
*/
#ifndef _MTP_TYPES_H
#define _MTP_TYPES_H
#include <stdint.h>
#include <vector>
#include <utils/Vector.h>
#include <utils/String8.h>
typedef int32_t int128_t[4];
typedef uint32_t uint128_t[4];
typedef uint16_t MtpOperationCode;
typedef uint16_t MtpResponseCode;
typedef uint16_t MtpEventCode;
typedef uint32_t MtpSessionID;
typedef uint32_t MtpStorageID;
typedef uint32_t MtpTransactionID;
typedef uint16_t MtpPropertyCode;
typedef uint16_t MtpDataType;
typedef uint16_t MtpObjectFormat;
typedef MtpPropertyCode MtpDeviceProperty;
typedef MtpPropertyCode MtpObjectProperty;
// object handles are unique across all storage but only within a single session.
// object handles cannot be reused after an object is deleted.
// values 0x00000000 and 0xFFFFFFFF are reserved for special purposes.
typedef uint32_t MtpObjectHandle;
// Special values
#define MTP_PARENT_ROOT 0xFFFFFFFF // parent is root of the storage
#define kInvalidObjectHandle 0xFFFFFFFF
class MtpStorage;
class MtpDevice;
class MtpProperty;
typedef android::Vector<MtpStorage*> MtpStorageList;
typedef android::Vector<MtpDevice*> MtpDeviceList;
typedef android::Vector<MtpProperty*> MtpPropertyList;
typedef android::Vector<uint8_t> UInt8List;
typedef android::Vector<uint16_t> UInt16List;
typedef android::Vector<uint32_t> UInt32List;
typedef android::Vector<uint64_t> UInt64List;
typedef android::Vector<int8_t> Int8List;
typedef android::Vector<int16_t> Int16List;
typedef android::Vector<int32_t> Int32List;
typedef android::Vector<int64_t> Int64List;
typedef UInt16List MtpObjectPropertyList;
typedef UInt16List MtpDevicePropertyList;
typedef UInt16List MtpObjectFormatList;
typedef UInt32List MtpObjectHandleList;
typedef UInt16List MtpObjectPropertyList;
typedef UInt32List MtpStorageIDList;
typedef android::String8 MtpString;
#endif // _MTP_TYPES_H
+78
View File
@@ -0,0 +1,78 @@
/*
* 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 <stdio.h>
#include <time.h>
#include <cutils/tztime.h>
#include "MtpUtils.h"
/*
DateTime strings follow a compatible subset of the definition found in ISO 8601, and
take the form of a Unicode string formatted as: "YYYYMMDDThhmmss.s". In this
representation, YYYY shall be replaced by the year, MM replaced by the month (01-12),
DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date,
hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the
second (00-59). The ".s" is optional, and represents tenths of a second.
*/
bool parseDateTime(const char* dateTime, time_t& outSeconds) {
int year, month, day, hour, minute, second;
struct tm tm;
if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d",
&year, &month, &day, &hour, &minute, &second) != 6)
return false;
const char* tail = dateTime + 15;
// skip optional tenth of second
if (tail[0] == '.' && tail[1])
tail += 2;
//FIXME - support +/-hhmm
bool useUTC = (tail[0] == 'Z');
// hack to compute timezone
time_t dummy;
localtime_r(&dummy, &tm);
tm.tm_sec = second;
tm.tm_min = minute;
tm.tm_hour = hour;
tm.tm_mday = day;
tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range
tm.tm_year = year - 1900;
tm.tm_wday = 0;
tm.tm_isdst = -1;
if (useUTC)
outSeconds = mktime(&tm);
else
outSeconds = mktime_tz(&tm, tm.tm_zone);
return true;
}
void formatDateTime(time_t seconds, char* buffer, int bufferLength) {
struct tm tm;
localtime_r(&seconds, &tm);
snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",
tm.tm_year + 1900,
tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
Executable
+27
View File
@@ -0,0 +1,27 @@
/*
* 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++
*/
#ifndef _MTP_UTILS_H
#define _MTP_UTILS_H
#include <stdint.h>
bool parseDateTime(const char* dateTime, time_t& outSeconds);
void formatDateTime(time_t seconds, char* buffer, int bufferLength);
#endif // _MTP_UTILS_H
Executable
+308
View File
@@ -0,0 +1,308 @@
/*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*
* 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.
*/
#include <iostream>
#include <utils/threads.h>
#include "btree.hpp"
#include "MtpDebug.h"
// Constructor
Tree::Tree() {
root = NULL;
count = 0;
}
// Destructor
Tree::~Tree() {
freeNode(root);
}
// Free the node
void Tree::freeNode(Node* leaf)
{
if ( leaf != NULL )
{
freeNode(leaf->Left());
freeNode(leaf->Right());
delete leaf;
}
}
int Tree::getCount(void) {
MTPD("node count: %d\n", count);
return count;
}
Node* Tree::addNode(int mtpid, std::string path)
{
MTPD("root: %d\n", root);
// No elements. Add the root
if ( root == NULL ) {
Node* n = new Node();
count++;
MTPD("node count: %d\n", count);
MTPD("adding node address: %d\n", n);
MTPD("adding mtpid: %d\n", mtpid);
n->setMtpid(mtpid);
n->setPath(path);
root = n;
MTPD("set root to %d\n", root);
return n;
}
else {
count++;
MTPD("node count: %d\n", count);
MTPD("adding new child node\n");
return addNode(mtpid, root, path);
}
}
// Add a node (private)
Node* Tree::addNode(int mtpid, Node* leaf, std::string path) {
Node* n;
if ( mtpid <= leaf->Mtpid() )
{
if ( leaf->Left() != NULL )
return addNode(mtpid, leaf->Left(), path);
else {
n = new Node();
MTPD("adding mtpid: %d node: %d\n", mtpid, n);
n->setMtpid(mtpid);
n->setPath(path);
n->setParent(leaf);
leaf->setLeft(n);
}
}
else
{
if ( leaf->Right() != NULL )
return addNode(mtpid, leaf->Right(), path);
else {
n = new Node();
MTPD("adding mtpid: %d node: %d\n", mtpid, n);
n->setMtpid(mtpid);
n->setPath(path);
n->setParent(leaf);
leaf->setRight(n);
}
}
return n;
}
void Tree::setMtpParentId(int mtpparentid, Node* node) {
node->setMtpParentId(mtpparentid);
}
std::string Tree::getPath(Node* node) {
return node->getPath();
}
int Tree::getMtpParentId(Node* node) {
return node->getMtpParentId();
}
Node* Tree::findNodePath(std::string path, Node* node) {
Node* n;
if ( node == NULL ) {
return NULL;
}
if ( node->getPath().compare(path) == 0 && node->Mtpid() > 0) {
return node;
}
else {
n = findNodePath(path, node->Left());
if (n)
return n;
n = findNodePath(path, node->Right());
if (n)
return n;
}
return NULL;
}
Node* Tree::getNext(Node *node) {
if (node == NULL)
return NULL;
else {
if (node->Left() != NULL)
return node->Left();
if (node->Right() != NULL)
return node->Right();
}
return NULL;
}
Node* Tree::findNode(int key, Node* node) {
//MTPD("key: %d\n", key);
//MTPD("node: %d\n", node);
if ( node == NULL ) {
return NULL;
}
else if ( node->Mtpid() == key ) {
return node;
}
else if ( key <= node->Mtpid() ) {
return findNode(key, node->Left());
}
else if ( key > node->Mtpid() ) {
return findNode(key, node->Right());
}
else {
return NULL;
}
return NULL;
}
void Tree::getmtpids(Node* node, std::vector<int>* mtpids)
{
if ( node )
{
MTPD("node: %d\n", node->Mtpid());
mtpids->push_back(node->Mtpid());
if (node->Left())
getmtpids(node->Left(), mtpids);
if (node->Right())
getmtpids(node->Right(), mtpids);
} else {
mtpids->push_back(0);
}
return;
}
// Find the node with min key
// Traverse the left sub-tree recursively
// till left sub-tree is empty to get min
Node* Tree::min(Node* node)
{
if ( node == NULL )
return NULL;
if ( node->Left() )
min(node->Left());
else
return node;
return NULL;
}
// Find the node with max key
// Traverse the right sub-tree recursively
// till right sub-tree is empty to get max
Node* Tree::max(Node* node)
{
if ( node == NULL )
return NULL;
if ( node->Right() )
max(node->Right());
else
return node;
return NULL;
}
// Find successor to a node
// Find the node, get the node with max value
// for the right sub-tree to get the successor
Node* Tree::successor(int key, Node *node)
{
Node* thisKey = findNode(key, node);
if ( thisKey )
return max(thisKey->Right());
return NULL;
}
// Find predecessor to a node
// Find the node, get the node with max value
// for the left sub-tree to get the predecessor
Node* Tree::predecessor(int key, Node *node)
{
Node* thisKey = findNode(key, node);
if ( thisKey )
return max(thisKey->Left());
return NULL;
}
void Tree::deleteNode(int key)
{
// Find the node.
Node* thisKey = findNode(key, root);
MTPD("Tree::deleteNode found node: %d\n", thisKey);
MTPD("handle: %d\n", thisKey->Mtpid());
if (thisKey == root) {
if (thisKey->Right()) {
root = thisKey->Right();
root->setParent(NULL);
return;
}
if (thisKey->Left()) {
root = thisKey->Left();
root->setParent(NULL);
return;
}
root = NULL;
delete thisKey;
return;
}
if ( thisKey->Left() == NULL && thisKey->Right() == NULL )
{
if ( thisKey->Mtpid() > thisKey->Parent()->Mtpid() ) {
thisKey->Parent()->setRight(NULL);
}
else {
thisKey->Parent()->setLeft(NULL);
}
delete thisKey;
return;
}
if ( thisKey->Left() == NULL && thisKey->Right() != NULL )
{
if ( thisKey->Mtpid() > thisKey->Parent()->Mtpid() )
thisKey->Parent()->setRight(thisKey->Right());
else
thisKey->Parent()->setLeft(thisKey->Right());
thisKey->Right()->setParent(thisKey->Parent());
delete thisKey;
return;
}
if ( thisKey->Left() != NULL && thisKey->Right() == NULL )
{
if ( thisKey->Mtpid() > thisKey->Parent()->Mtpid() )
thisKey->Parent()->setRight(thisKey->Left());
else
thisKey->Parent()->setLeft(thisKey->Left());
thisKey->Left()->setParent(thisKey->Parent());
delete thisKey;
return;
}
if ( thisKey->Left() != NULL && thisKey->Right() != NULL )
{
Node* sub = predecessor(thisKey->Mtpid(), thisKey);
if ( sub == NULL )
sub = successor(thisKey->Mtpid(), thisKey);
if ( sub->Parent()->Mtpid() <= sub->Mtpid() )
sub->Parent()->setRight(sub->Right());
else
sub->Parent()->setLeft(sub->Left());
thisKey->setMtpid(sub->Mtpid());
delete sub;
return;
}
}
Executable
+94
View File
@@ -0,0 +1,94 @@
/*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*
* 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.
*/
#ifndef BTREE_HPP
#define BTREE_HPP
#include <iostream>
#include <vector>
#include <utils/threads.h>
#include "MtpDebug.h"
// A generic tree node class
class Node {
int mtpid;
int mtpparentid;
std::string path;
int parentID;
Node* left;
Node* right;
Node* parent;
public:
Node();
void setMtpid(int aMtpid);
void setPath(std::string aPath);
void setLeft(Node* aLeft);
void setRight(Node* aRight);
void setParent(Node* aParent);
void setMtpParentId(int id);
int Mtpid();
int getMtpParentId();
std::string getPath();
Node* Left();
Node* Right();
Node* Parent();
void addProperty(uint64_t property, uint64_t valueInt, std::string valueStr, int dataType);
void updateProperty(uint64_t property, uint64_t valueInt, std::string valueStr, int dataType);
void addProperties(int storageID, int parent_object);
uint64_t getIntProperty(uint64_t property);
struct mtpProperty {
uint64_t property;
uint64_t valueInt;
std::string valueStr;
int dataType;
};
std::vector<mtpProperty>& getMtpProps();
std::vector<mtpProperty> mtpProp;
};
// Binary Search Tree class
class Tree {
Node* root;
public:
Tree();
~Tree();
Node* Root() {
MTPD("root: %d\n", root);
return root;
};
Node* addNode(int mtpid, std::string path);
void setMtpParentId(int mtpparentid, Node* node);
Node* findNode(int key, Node* parent);
void getmtpids(Node* node, std::vector<int>* mtpids);
void deleteNode(int key);
Node* min(Node* node);
Node* max(Node* node);
Node* successor(int key, Node* parent);
Node* predecessor(int key, Node* parent);
std::string getPath(Node* node);
int getMtpParentId(Node* node);
Node* findNodePath(std::string path, Node* node);
Node* getNext(Node* node);
int getCount();
private:
Node* addNode(int mtpid, Node* leaf, std::string path);
void freeNode(Node* leaf);
int count;
};
#endif
Executable
+607
View File
@@ -0,0 +1,607 @@
/*
* 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++
*/
#ifndef _MTP_H
#define _MTP_H
#include <stdint.h>
#include <stdlib.h>
#define MTP_STANDARD_VERSION 100
// Container Types
#define MTP_CONTAINER_TYPE_UNDEFINED 0
#define MTP_CONTAINER_TYPE_COMMAND 1
#define MTP_CONTAINER_TYPE_DATA 2
#define MTP_CONTAINER_TYPE_RESPONSE 3
#define MTP_CONTAINER_TYPE_EVENT 4
// Container Offsets
#define MTP_CONTAINER_LENGTH_OFFSET 0
#define MTP_CONTAINER_TYPE_OFFSET 4
#define MTP_CONTAINER_CODE_OFFSET 6
#define MTP_CONTAINER_TRANSACTION_ID_OFFSET 8
#define MTP_CONTAINER_PARAMETER_OFFSET 12
#define MTP_CONTAINER_HEADER_SIZE 12
// MTP Data Types
#define MTP_TYPE_UNDEFINED 0x0000 // Undefined
#define MTP_TYPE_INT8 0x0001 // Signed 8-bit integer
#define MTP_TYPE_UINT8 0x0002 // Unsigned 8-bit integer
#define MTP_TYPE_INT16 0x0003 // Signed 16-bit integer
#define MTP_TYPE_UINT16 0x0004 // Unsigned 16-bit integer
#define MTP_TYPE_INT32 0x0005 // Signed 32-bit integer
#define MTP_TYPE_UINT32 0x0006 // Unsigned 32-bit integer
#define MTP_TYPE_INT64 0x0007 // Signed 64-bit integer
#define MTP_TYPE_UINT64 0x0008 // Unsigned 64-bit integer
#define MTP_TYPE_INT128 0x0009 // Signed 128-bit integer
#define MTP_TYPE_UINT128 0x000A // Unsigned 128-bit integer
#define MTP_TYPE_AINT8 0x4001 // Array of signed 8-bit integers
#define MTP_TYPE_AUINT8 0x4002 // Array of unsigned 8-bit integers
#define MTP_TYPE_AINT16 0x4003 // Array of signed 16-bit integers
#define MTP_TYPE_AUINT16 0x4004 // Array of unsigned 16-bit integers
#define MTP_TYPE_AINT32 0x4005 // Array of signed 32-bit integers
#define MTP_TYPE_AUINT32 0x4006 // Array of unsigned 32-bit integers
#define MTP_TYPE_AINT64 0x4007 // Array of signed 64-bit integers
#define MTP_TYPE_AUINT64 0x4008 // Array of unsigned 64-bit integers
#define MTP_TYPE_AINT128 0x4009 // Array of signed 128-bit integers
#define MTP_TYPE_AUINT128 0x400A // Array of unsigned 128-bit integers
#define MTP_TYPE_STR 0xFFFF // Variable-length Unicode string
// MTP Format Codes
#define MTP_FORMAT_UNDEFINED 0x3000 // Undefined object
#define MTP_FORMAT_ASSOCIATION 0x3001 // Association (for example, a folder)
#define MTP_FORMAT_SCRIPT 0x3002 // Device model-specific script
#define MTP_FORMAT_EXECUTABLE 0x3003 // Device model-specific binary executable
#define MTP_FORMAT_TEXT 0x3004 // Text file
#define MTP_FORMAT_HTML 0x3005 // Hypertext Markup Language file (text)
#define MTP_FORMAT_DPOF 0x3006 // Digital Print Order Format file (text)
#define MTP_FORMAT_AIFF 0x3007 // Audio clip
#define MTP_FORMAT_WAV 0x3008 // Audio clip
#define MTP_FORMAT_MP3 0x3009 // Audio clip
#define MTP_FORMAT_AVI 0x300A // Video clip
#define MTP_FORMAT_MPEG 0x300B // Video clip
#define MTP_FORMAT_ASF 0x300C // Microsoft Advanced Streaming Format (video)
#define MTP_FORMAT_DEFINED 0x3800 // Unknown image object
#define MTP_FORMAT_EXIF_JPEG 0x3801 // Exchangeable File Format, JEIDA standard
#define MTP_FORMAT_TIFF_EP 0x3802 // Tag Image File Format for Electronic Photography
#define MTP_FORMAT_FLASHPIX 0x3803 // Structured Storage Image Format
#define MTP_FORMAT_BMP 0x3804 // Microsoft Windows Bitmap file
#define MTP_FORMAT_CIFF 0x3805 // Canon Camera Image File Format
#define MTP_FORMAT_GIF 0x3807 // Graphics Interchange Format
#define MTP_FORMAT_JFIF 0x3808 // JPEG File Interchange Format
#define MTP_FORMAT_CD 0x3809 // PhotoCD Image Pac
#define MTP_FORMAT_PICT 0x380A // Quickdraw Image Format
#define MTP_FORMAT_PNG 0x380B // Portable Network Graphics
#define MTP_FORMAT_TIFF 0x380D // Tag Image File Format
#define MTP_FORMAT_TIFF_IT 0x380E // Tag Image File Format for Information Technology (graphic arts)
#define MTP_FORMAT_JP2 0x380F // JPEG2000 Baseline File Format
#define MTP_FORMAT_JPX 0x3810 // JPEG2000 Extended File Format
#define MTP_FORMAT_UNDEFINED_FIRMWARE 0xB802
#define MTP_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881
#define MTP_FORMAT_UNDEFINED_AUDIO 0xB900
#define MTP_FORMAT_WMA 0xB901
#define MTP_FORMAT_OGG 0xB902
#define MTP_FORMAT_AAC 0xB903
#define MTP_FORMAT_AUDIBLE 0xB904
#define MTP_FORMAT_FLAC 0xB906
#define MTP_FORMAT_UNDEFINED_VIDEO 0xB980
#define MTP_FORMAT_WMV 0xB981
#define MTP_FORMAT_MP4_CONTAINER 0xB982 // ISO 14496-1
#define MTP_FORMAT_MP2 0xB983
#define MTP_FORMAT_3GP_CONTAINER 0xB984 // 3GPP file format. Details: http://www.3gpp.org/ftp/Specs/html-info/26244.htm (page title - \u201cTransparent end-to-end packet switched streaming service, 3GPP file format\u201d).
#define MTP_FORMAT_UNDEFINED_COLLECTION 0xBA00
#define MTP_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01
#define MTP_FORMAT_ABSTRACT_IMAGE_ALBUM 0xBA02
#define MTP_FORMAT_ABSTRACT_AUDIO_ALBUM 0xBA03
#define MTP_FORMAT_ABSTRACT_VIDEO_ALBUM 0xBA04
#define MTP_FORMAT_ABSTRACT_AV_PLAYLIST 0xBA05
#define MTP_FORMAT_ABSTRACT_CONTACT_GROUP 0xBA06
#define MTP_FORMAT_ABSTRACT_MESSAGE_FOLDER 0xBA07
#define MTP_FORMAT_ABSTRACT_CHAPTERED_PRODUCTION 0xBA08
#define MTP_FORMAT_ABSTRACT_AUDIO_PLAYLIST 0xBA09
#define MTP_FORMAT_ABSTRACT_VIDEO_PLAYLIST 0xBA0A
#define MTP_FORMAT_ABSTRACT_MEDIACAST 0xBA0B // For use with mediacasts; references multimedia enclosures of RSS feeds or episodic content
#define MTP_FORMAT_WPL_PLAYLIST 0xBA10
#define MTP_FORMAT_M3U_PLAYLIST 0xBA11
#define MTP_FORMAT_MPL_PLAYLIST 0xBA12
#define MTP_FORMAT_ASX_PLAYLIST 0xBA13
#define MTP_FORMAT_PLS_PLAYLIST 0xBA14
#define MTP_FORMAT_UNDEFINED_DOCUMENT 0xBA80
#define MTP_FORMAT_ABSTRACT_DOCUMENT 0xBA81
#define MTP_FORMAT_XML_DOCUMENT 0xBA82
#define MTP_FORMAT_MS_WORD_DOCUMENT 0xBA83
#define MTP_FORMAT_MHT_COMPILED_HTML_DOCUMENT 0xBA84
#define MTP_FORMAT_MS_EXCEL_SPREADSHEET 0xBA85
#define MTP_FORMAT_MS_POWERPOINT_PRESENTATION 0xBA86
#define MTP_FORMAT_UNDEFINED_MESSAGE 0xBB00
#define MTP_FORMAT_ABSTRACT_MESSSAGE 0xBB01
#define MTP_FORMAT_UNDEFINED_CONTACT 0xBB80
#define MTP_FORMAT_ABSTRACT_CONTACT 0xBB81
#define MTP_FORMAT_VCARD_2 0xBB82
// MTP Object Property Codes
#define MTP_PROPERTY_STORAGE_ID 0xDC01
#define MTP_PROPERTY_OBJECT_FORMAT 0xDC02
#define MTP_PROPERTY_PROTECTION_STATUS 0xDC03
#define MTP_PROPERTY_OBJECT_SIZE 0xDC04
#define MTP_PROPERTY_ASSOCIATION_TYPE 0xDC05
#define MTP_PROPERTY_ASSOCIATION_DESC 0xDC06
#define MTP_PROPERTY_OBJECT_FILE_NAME 0xDC07
#define MTP_PROPERTY_DATE_CREATED 0xDC08
#define MTP_PROPERTY_DATE_MODIFIED 0xDC09
#define MTP_PROPERTY_KEYWORDS 0xDC0A
#define MTP_PROPERTY_PARENT_OBJECT 0xDC0B
#define MTP_PROPERTY_ALLOWED_FOLDER_CONTENTS 0xDC0C
#define MTP_PROPERTY_HIDDEN 0xDC0D
#define MTP_PROPERTY_SYSTEM_OBJECT 0xDC0E
#define MTP_PROPERTY_PERSISTENT_UID 0xDC41
#define MTP_PROPERTY_SYNC_ID 0xDC42
#define MTP_PROPERTY_PROPERTY_BAG 0xDC43
#define MTP_PROPERTY_NAME 0xDC44
#define MTP_PROPERTY_CREATED_BY 0xDC45
#define MTP_PROPERTY_ARTIST 0xDC46
#define MTP_PROPERTY_DATE_AUTHORED 0xDC47
#define MTP_PROPERTY_DESCRIPTION 0xDC48
#define MTP_PROPERTY_URL_REFERENCE 0xDC49
#define MTP_PROPERTY_LANGUAGE_LOCALE 0xDC4A
#define MTP_PROPERTY_COPYRIGHT_INFORMATION 0xDC4B
#define MTP_PROPERTY_SOURCE 0xDC4C
#define MTP_PROPERTY_ORIGIN_LOCATION 0xDC4D
#define MTP_PROPERTY_DATE_ADDED 0xDC4E
#define MTP_PROPERTY_NON_CONSUMABLE 0xDC4F
#define MTP_PROPERTY_CORRUPT_UNPLAYABLE 0xDC50
#define MTP_PROPERTY_PRODUCER_SERIAL_NUMBER 0xDC51
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_SIZE 0xDC82
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DURATION 0xDC85
#define MTP_PROPERTY_REPRESENTATIVE_SAMPLE_DATA 0xDC86
#define MTP_PROPERTY_WIDTH 0xDC87
#define MTP_PROPERTY_HEIGHT 0xDC88
#define MTP_PROPERTY_DURATION 0xDC89
#define MTP_PROPERTY_RATING 0xDC8A
#define MTP_PROPERTY_TRACK 0xDC8B
#define MTP_PROPERTY_GENRE 0xDC8C
#define MTP_PROPERTY_CREDITS 0xDC8D
#define MTP_PROPERTY_LYRICS 0xDC8E
#define MTP_PROPERTY_SUBSCRIPTION_CONTENT_ID 0xDC8F
#define MTP_PROPERTY_PRODUCED_BY 0xDC90
#define MTP_PROPERTY_USE_COUNT 0xDC91
#define MTP_PROPERTY_SKIP_COUNT 0xDC92
#define MTP_PROPERTY_LAST_ACCESSED 0xDC93
#define MTP_PROPERTY_PARENTAL_RATING 0xDC94
#define MTP_PROPERTY_META_GENRE 0xDC95
#define MTP_PROPERTY_COMPOSER 0xDC96
#define MTP_PROPERTY_EFFECTIVE_RATING 0xDC97
#define MTP_PROPERTY_SUBTITLE 0xDC98
#define MTP_PROPERTY_ORIGINAL_RELEASE_DATE 0xDC99
#define MTP_PROPERTY_ALBUM_NAME 0xDC9A
#define MTP_PROPERTY_ALBUM_ARTIST 0xDC9B
#define MTP_PROPERTY_MOOD 0xDC9C
#define MTP_PROPERTY_DRM_STATUS 0xDC9D
#define MTP_PROPERTY_SUB_DESCRIPTION 0xDC9E
#define MTP_PROPERTY_IS_CROPPED 0xDCD1
#define MTP_PROPERTY_IS_COLOUR_CORRECTED 0xDCD2
#define MTP_PROPERTY_IMAGE_BIT_DEPTH 0xDCD3
#define MTP_PROPERTY_F_NUMBER 0xDCD4
#define MTP_PROPERTY_EXPOSURE_TIME 0xDCD5
#define MTP_PROPERTY_EXPOSURE_INDEX 0xDCD6
#define MTP_PROPERTY_TOTAL_BITRATE 0xDE91
#define MTP_PROPERTY_BITRATE_TYPE 0xDE92
#define MTP_PROPERTY_SAMPLE_RATE 0xDE93
#define MTP_PROPERTY_NUMBER_OF_CHANNELS 0xDE94
#define MTP_PROPERTY_AUDIO_BIT_DEPTH 0xDE95
#define MTP_PROPERTY_SCAN_TYPE 0xDE97
#define MTP_PROPERTY_AUDIO_WAVE_CODEC 0xDE99
#define MTP_PROPERTY_AUDIO_BITRATE 0xDE9A
#define MTP_PROPERTY_VIDEO_FOURCC_CODEC 0xDE9B
#define MTP_PROPERTY_VIDEO_BITRATE 0xDE9C
#define MTP_PROPERTY_FRAMES_PER_THOUSAND_SECONDS 0xDE9D
#define MTP_PROPERTY_KEYFRAME_DISTANCE 0xDE9E
#define MTP_PROPERTY_BUFFER_SIZE 0xDE9F
#define MTP_PROPERTY_ENCODING_QUALITY 0xDEA0
#define MTP_PROPERTY_ENCODING_PROFILE 0xDEA1
#define MTP_PROPERTY_DISPLAY_NAME 0xDCE0
#define MTP_PROPERTY_BODY_TEXT 0xDCE1
#define MTP_PROPERTY_SUBJECT 0xDCE2
#define MTP_PROPERTY_PRIORITY 0xDCE3
#define MTP_PROPERTY_GIVEN_NAME 0xDD00
#define MTP_PROPERTY_MIDDLE_NAMES 0xDD01
#define MTP_PROPERTY_FAMILY_NAME 0xDD02
#define MTP_PROPERTY_PREFIX 0xDD03
#define MTP_PROPERTY_SUFFIX 0xDD04
#define MTP_PROPERTY_PHONETIC_GIVEN_NAME 0xDD05
#define MTP_PROPERTY_PHONETIC_FAMILY_NAME 0xDD06
#define MTP_PROPERTY_EMAIL_PRIMARY 0xDD07
#define MTP_PROPERTY_EMAIL_PERSONAL_1 0xDD08
#define MTP_PROPERTY_EMAIL_PERSONAL_2 0xDD09
#define MTP_PROPERTY_EMAIL_BUSINESS_1 0xDD0A
#define MTP_PROPERTY_EMAIL_BUSINESS_2 0xDD0B
#define MTP_PROPERTY_EMAIL_OTHERS 0xDD0C
#define MTP_PROPERTY_PHONE_NUMBER_PRIMARY 0xDD0D
#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL 0xDD0E
#define MTP_PROPERTY_PHONE_NUMBER_PERSONAL_2 0xDD0F
#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS 0xDD10
#define MTP_PROPERTY_PHONE_NUMBER_BUSINESS_2 0xDD11
#define MTP_PROPERTY_PHONE_NUMBER_MOBILE 0xDD12
#define MTP_PROPERTY_PHONE_NUMBER_MOBILE_2 0xDD13
#define MTP_PROPERTY_FAX_NUMBER_PRIMARY 0xDD14
#define MTP_PROPERTY_FAX_NUMBER_PERSONAL 0xDD15
#define MTP_PROPERTY_FAX_NUMBER_BUSINESS 0xDD16
#define MTP_PROPERTY_PAGER_NUMBER 0xDD17
#define MTP_PROPERTY_PHONE_NUMBER_OTHERS 0xDD18
#define MTP_PROPERTY_PRIMARY_WEB_ADDRESS 0xDD19
#define MTP_PROPERTY_PERSONAL_WEB_ADDRESS 0xDD1A
#define MTP_PROPERTY_BUSINESS_WEB_ADDRESS 0xDD1B
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS 0xDD1C
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_2 0xDD1D
#define MTP_PROPERTY_INSTANT_MESSANGER_ADDRESS_3 0xDD1E
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1F
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24
#define MTP_PROPERTY_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2A
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2B
#define MTP_PROPERTY_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2C
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_FULL 0xDD2D
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2E
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2F
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_CITY 0xDD30
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_REGION 0xDD31
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32
#define MTP_PROPERTY_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33
#define MTP_PROPERTY_ORGANIZATION_NAME 0xDD34
#define MTP_PROPERTY_PHONETIC_ORGANIZATION_NAME 0xDD35
#define MTP_PROPERTY_ROLE 0xDD36
#define MTP_PROPERTY_BIRTHDATE 0xDD37
#define MTP_PROPERTY_MESSAGE_TO 0xDD40
#define MTP_PROPERTY_MESSAGE_CC 0xDD41
#define MTP_PROPERTY_MESSAGE_BCC 0xDD42
#define MTP_PROPERTY_MESSAGE_READ 0xDD43
#define MTP_PROPERTY_MESSAGE_RECEIVED_TIME 0xDD44
#define MTP_PROPERTY_MESSAGE_SENDER 0xDD45
#define MTP_PROPERTY_ACTIVITY_BEGIN_TIME 0xDD50
#define MTP_PROPERTY_ACTIVITY_END_TIME 0xDD51
#define MTP_PROPERTY_ACTIVITY_LOCATION 0xDD52
#define MTP_PROPERTY_ACTIVITY_REQUIRED_ATTENDEES 0xDD54
#define MTP_PROPERTY_ACTIVITY_OPTIONAL_ATTENDEES 0xDD55
#define MTP_PROPERTY_ACTIVITY_RESOURCES 0xDD56
#define MTP_PROPERTY_ACTIVITY_ACCEPTED 0xDD57
#define MTP_PROPERTY_ACTIVITY_TENTATIVE 0xDD58
#define MTP_PROPERTY_ACTIVITY_DECLINED 0xDD59
#define MTP_PROPERTY_ACTIVITY_REMAINDER_TIME 0xDD5A
#define MTP_PROPERTY_ACTIVITY_OWNER 0xDD5B
#define MTP_PROPERTY_ACTIVITY_STATUS 0xDD5C
#define MTP_PROPERTY_OWNER 0xDD5D
#define MTP_PROPERTY_EDITOR 0xDD5E
#define MTP_PROPERTY_WEBMASTER 0xDD5F
#define MTP_PROPERTY_URL_SOURCE 0xDD60
#define MTP_PROPERTY_URL_DESTINATION 0xDD61
#define MTP_PROPERTY_TIME_BOOKMARK 0xDD62
#define MTP_PROPERTY_OBJECT_BOOKMARK 0xDD63
#define MTP_PROPERTY_BYTE_BOOKMARK 0xDD64
#define MTP_PROPERTY_LAST_BUILD_DATE 0xDD70
#define MTP_PROPERTY_TIME_TO_LIVE 0xDD71
#define MTP_PROPERTY_MEDIA_GUID 0xDD72
// MTP Device Property Codes
#define MTP_DEVICE_PROPERTY_UNDEFINED 0x5000
#define MTP_DEVICE_PROPERTY_BATTERY_LEVEL 0x5001
#define MTP_DEVICE_PROPERTY_FUNCTIONAL_MODE 0x5002
#define MTP_DEVICE_PROPERTY_IMAGE_SIZE 0x5003
#define MTP_DEVICE_PROPERTY_COMPRESSION_SETTING 0x5004
#define MTP_DEVICE_PROPERTY_WHITE_BALANCE 0x5005
#define MTP_DEVICE_PROPERTY_RGB_GAIN 0x5006
#define MTP_DEVICE_PROPERTY_F_NUMBER 0x5007
#define MTP_DEVICE_PROPERTY_FOCAL_LENGTH 0x5008
#define MTP_DEVICE_PROPERTY_FOCUS_DISTANCE 0x5009
#define MTP_DEVICE_PROPERTY_FOCUS_MODE 0x500A
#define MTP_DEVICE_PROPERTY_EXPOSURE_METERING_MODE 0x500B
#define MTP_DEVICE_PROPERTY_FLASH_MODE 0x500C
#define MTP_DEVICE_PROPERTY_EXPOSURE_TIME 0x500D
#define MTP_DEVICE_PROPERTY_EXPOSURE_PROGRAM_MODE 0x500E
#define MTP_DEVICE_PROPERTY_EXPOSURE_INDEX 0x500F
#define MTP_DEVICE_PROPERTY_EXPOSURE_BIAS_COMPENSATION 0x5010
#define MTP_DEVICE_PROPERTY_DATETIME 0x5011
#define MTP_DEVICE_PROPERTY_CAPTURE_DELAY 0x5012
#define MTP_DEVICE_PROPERTY_STILL_CAPTURE_MODE 0x5013
#define MTP_DEVICE_PROPERTY_CONTRAST 0x5014
#define MTP_DEVICE_PROPERTY_SHARPNESS 0x5015
#define MTP_DEVICE_PROPERTY_DIGITAL_ZOOM 0x5016
#define MTP_DEVICE_PROPERTY_EFFECT_MODE 0x5017
#define MTP_DEVICE_PROPERTY_BURST_NUMBER 0x5018
#define MTP_DEVICE_PROPERTY_BURST_INTERVAL 0x5019
#define MTP_DEVICE_PROPERTY_TIMELAPSE_NUMBER 0x501A
#define MTP_DEVICE_PROPERTY_TIMELAPSE_INTERVAL 0x501B
#define MTP_DEVICE_PROPERTY_FOCUS_METERING_MODE 0x501C
#define MTP_DEVICE_PROPERTY_UPLOAD_URL 0x501D
#define MTP_DEVICE_PROPERTY_ARTIST 0x501E
#define MTP_DEVICE_PROPERTY_COPYRIGHT_INFO 0x501F
#define MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER 0xD401
#define MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME 0xD402
#define MTP_DEVICE_PROPERTY_VOLUME 0xD403
#define MTP_DEVICE_PROPERTY_SUPPORTED_FORMATS_ORDERED 0xD404
#define MTP_DEVICE_PROPERTY_DEVICE_ICON 0xD405
#define MTP_DEVICE_PROPERTY_PLAYBACK_RATE 0xD410
#define MTP_DEVICE_PROPERTY_PLAYBACK_OBJECT 0xD411
#define MTP_DEVICE_PROPERTY_PLAYBACK_CONTAINER_INDEX 0xD412
#define MTP_DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO 0xD406
#define MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE 0xD407
// MTP Operation Codes
#define MTP_OPERATION_GET_DEVICE_INFO 0x1001
#define MTP_OPERATION_OPEN_SESSION 0x1002
#define MTP_OPERATION_CLOSE_SESSION 0x1003
#define MTP_OPERATION_GET_STORAGE_IDS 0x1004
#define MTP_OPERATION_GET_STORAGE_INFO 0x1005
#define MTP_OPERATION_GET_NUM_OBJECTS 0x1006
#define MTP_OPERATION_GET_OBJECT_HANDLES 0x1007
#define MTP_OPERATION_GET_OBJECT_INFO 0x1008
#define MTP_OPERATION_GET_OBJECT 0x1009
#define MTP_OPERATION_GET_THUMB 0x100A
#define MTP_OPERATION_DELETE_OBJECT 0x100B
#define MTP_OPERATION_SEND_OBJECT_INFO 0x100C
#define MTP_OPERATION_SEND_OBJECT 0x100D
#define MTP_OPERATION_INITIATE_CAPTURE 0x100E
#define MTP_OPERATION_FORMAT_STORE 0x100F
#define MTP_OPERATION_RESET_DEVICE 0x1010
#define MTP_OPERATION_SELF_TEST 0x1011
#define MTP_OPERATION_SET_OBJECT_PROTECTION 0x1012
#define MTP_OPERATION_POWER_DOWN 0x1013
#define MTP_OPERATION_GET_DEVICE_PROP_DESC 0x1014
#define MTP_OPERATION_GET_DEVICE_PROP_VALUE 0x1015
#define MTP_OPERATION_SET_DEVICE_PROP_VALUE 0x1016
#define MTP_OPERATION_RESET_DEVICE_PROP_VALUE 0x1017
#define MTP_OPERATION_TERMINATE_OPEN_CAPTURE 0x1018
#define MTP_OPERATION_MOVE_OBJECT 0x1019
#define MTP_OPERATION_COPY_OBJECT 0x101A
#define MTP_OPERATION_GET_PARTIAL_OBJECT 0x101B
#define MTP_OPERATION_INITIATE_OPEN_CAPTURE 0x101C
#define MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED 0x9801
#define MTP_OPERATION_GET_OBJECT_PROP_DESC 0x9802
#define MTP_OPERATION_GET_OBJECT_PROP_VALUE 0x9803
#define MTP_OPERATION_SET_OBJECT_PROP_VALUE 0x9804
#define MTP_OPERATION_GET_OBJECT_PROP_LIST 0x9805
#define MTP_OPERATION_SET_OBJECT_PROP_LIST 0x9806
#define MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC 0x9807
#define MTP_OPERATION_SEND_OBJECT_PROP_LIST 0x9808
#define MTP_OPERATION_GET_OBJECT_REFERENCES 0x9810
#define MTP_OPERATION_SET_OBJECT_REFERENCES 0x9811
#define MTP_OPERATION_SKIP 0x9820
// Android extensions for direct file IO
// Same as GetPartialObject, but with 64 bit offset
#define MTP_OPERATION_GET_PARTIAL_OBJECT_64 0x95C1
// Same as GetPartialObject64, but copying host to device
#define MTP_OPERATION_SEND_PARTIAL_OBJECT 0x95C2
// Truncates file to 64 bit length
#define MTP_OPERATION_TRUNCATE_OBJECT 0x95C3
// Must be called before using SendPartialObject and TruncateObject
#define MTP_OPERATION_BEGIN_EDIT_OBJECT 0x95C4
// Called to commit changes made by SendPartialObject and TruncateObject
#define MTP_OPERATION_END_EDIT_OBJECT 0x95C5
// MTP Response Codes
#define MTP_RESPONSE_UNDEFINED 0x2000
#define MTP_RESPONSE_OK 0x2001
#define MTP_RESPONSE_GENERAL_ERROR 0x2002
#define MTP_RESPONSE_SESSION_NOT_OPEN 0x2003
#define MTP_RESPONSE_INVALID_TRANSACTION_ID 0x2004
#define MTP_RESPONSE_OPERATION_NOT_SUPPORTED 0x2005
#define MTP_RESPONSE_PARAMETER_NOT_SUPPORTED 0x2006
#define MTP_RESPONSE_INCOMPLETE_TRANSFER 0x2007
#define MTP_RESPONSE_INVALID_STORAGE_ID 0x2008
#define MTP_RESPONSE_INVALID_OBJECT_HANDLE 0x2009
#define MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED 0x200A
#define MTP_RESPONSE_INVALID_OBJECT_FORMAT_CODE 0x200B
#define MTP_RESPONSE_STORAGE_FULL 0x200C
#define MTP_RESPONSE_OBJECT_WRITE_PROTECTED 0x200D
#define MTP_RESPONSE_STORE_READ_ONLY 0x200E
#define MTP_RESPONSE_ACCESS_DENIED 0x200F
#define MTP_RESPONSE_NO_THUMBNAIL_PRESENT 0x2010
#define MTP_RESPONSE_SELF_TEST_FAILED 0x2011
#define MTP_RESPONSE_PARTIAL_DELETION 0x2012
#define MTP_RESPONSE_STORE_NOT_AVAILABLE 0x2013
#define MTP_RESPONSE_SPECIFICATION_BY_FORMAT_UNSUPPORTED 0x2014
#define MTP_RESPONSE_NO_VALID_OBJECT_INFO 0x2015
#define MTP_RESPONSE_INVALID_CODE_FORMAT 0x2016
#define MTP_RESPONSE_UNKNOWN_VENDOR_CODE 0x2017
#define MTP_RESPONSE_CAPTURE_ALREADY_TERMINATED 0x2018
#define MTP_RESPONSE_DEVICE_BUSY 0x2019
#define MTP_RESPONSE_INVALID_PARENT_OBJECT 0x201A
#define MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT 0x201B
#define MTP_RESPONSE_INVALID_DEVICE_PROP_VALUE 0x201C
#define MTP_RESPONSE_INVALID_PARAMETER 0x201D
#define MTP_RESPONSE_SESSION_ALREADY_OPEN 0x201E
#define MTP_RESPONSE_TRANSACTION_CANCELLED 0x201F
#define MTP_RESPONSE_SPECIFICATION_OF_DESTINATION_UNSUPPORTED 0x2020
#define MTP_RESPONSE_INVALID_OBJECT_PROP_CODE 0xA801
#define MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT 0xA802
#define MTP_RESPONSE_INVALID_OBJECT_PROP_VALUE 0xA803
#define MTP_RESPONSE_INVALID_OBJECT_REFERENCE 0xA804
#define MTP_RESPONSE_GROUP_NOT_SUPPORTED 0xA805
#define MTP_RESPONSE_INVALID_DATASET 0xA806
#define MTP_RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807
#define MTP_RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED 0xA808
#define MTP_RESPONSE_OBJECT_TOO_LARGE 0xA809
#define MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED 0xA80A
// MTP Event Codes
#define MTP_EVENT_UNDEFINED 0x4000
#define MTP_EVENT_CANCEL_TRANSACTION 0x4001
#define MTP_EVENT_OBJECT_ADDED 0x4002
#define MTP_EVENT_OBJECT_REMOVED 0x4003
#define MTP_EVENT_STORE_ADDED 0x4004
#define MTP_EVENT_STORE_REMOVED 0x4005
#define MTP_EVENT_DEVICE_PROP_CHANGED 0x4006
#define MTP_EVENT_OBJECT_INFO_CHANGED 0x4007
#define MTP_EVENT_DEVICE_INFO_CHANGED 0x4008
#define MTP_EVENT_REQUEST_OBJECT_TRANSFER 0x4009
#define MTP_EVENT_STORE_FULL 0x400A
#define MTP_EVENT_DEVICE_RESET 0x400B
#define MTP_EVENT_STORAGE_INFO_CHANGED 0x400C
#define MTP_EVENT_CAPTURE_COMPLETE 0x400D
#define MTP_EVENT_UNREPORTED_STATUS 0x400E
#define MTP_EVENT_OBJECT_PROP_CHANGED 0xC801
#define MTP_EVENT_OBJECT_PROP_DESC_CHANGED 0xC802
#define MTP_EVENT_OBJECT_REFERENCES_CHANGED 0xC803
// Storage Type
#define MTP_STORAGE_FIXED_ROM 0x0001
#define MTP_STORAGE_REMOVABLE_ROM 0x0002
#define MTP_STORAGE_FIXED_RAM 0x0003
#define MTP_STORAGE_REMOVABLE_RAM 0x0004
// Storage File System
#define MTP_STORAGE_FILESYSTEM_FLAT 0x0001
#define MTP_STORAGE_FILESYSTEM_HIERARCHICAL 0x0002
#define MTP_STORAGE_FILESYSTEM_DCF 0x0003
// Storage Access Capability
#define MTP_STORAGE_READ_WRITE 0x0000
#define MTP_STORAGE_READ_ONLY_WITHOUT_DELETE 0x0001
#define MTP_STORAGE_READ_ONLY_WITH_DELETE 0x0002
// Association Type
#define MTP_ASSOCIATION_TYPE_UNDEFINED 0x0000
#define MTP_ASSOCIATION_TYPE_GENERIC_FOLDER 0x0001
// Supported Playback Formats
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED 0x3000
/** Format code for associations (folders and directories) */
#define SUPPORTED_PLAYBACK_FORMAT_ASSOCIATION 0x3001
/** Format code for script files */
#define SUPPORTED_PLAYBACK_FORMAT_SCRIPT 0x3002
/** Format code for executable files */
#define SUPPORTED_PLAYBACK_FORMAT_EXECUTABLE 0x3003
/** Format code for text files */
#define SUPPORTED_PLAYBACK_FORMAT_TEXT 0x3004
/** Format code for HTML files */
#define SUPPORTED_PLAYBACK_FORMAT_HTML 0x3005
/** Format code for DPOF files */
#define SUPPORTED_PLAYBACK_FORMAT_DPOF 0x3006
/** Format code for AIFF audio files */
#define SUPPORTED_PLAYBACK_FORMAT_AIFF 0x3007
/** Format code for WAV audio files */
#define SUPPORTED_PLAYBACK_FORMAT_WAV 0x3008
/** Format code for MP3 audio files */
#define SUPPORTED_PLAYBACK_FORMAT_MP3 0x3009
/** Format code for AVI video files */
#define SUPPORTED_PLAYBACK_FORMAT_AVI 0x300A
/** Format code for MPEG video files */
#define SUPPORTED_PLAYBACK_FORMAT_MPEG 0x300B
/** Format code for ASF files */
#define SUPPORTED_PLAYBACK_FORMAT_ASF 0x300C
/** Format code for JPEG image files */
#define SUPPORTED_PLAYBACK_FORMAT_EXIF_JPEG 0x3801
/** Format code for TIFF EP image files */
#define SUPPORTED_PLAYBACK_FORMAT_TIFF_EP 0x3802
/** Format code for BMP image files */
#define SUPPORTED_PLAYBACK_FORMAT_BMP 0x3804
/** Format code for GIF image files */
#define SUPPORTED_PLAYBACK_FORMAT_GIF 0x3807
/** Format code for JFIF image files */
#define SUPPORTED_PLAYBACK_FORMAT_JFIF 0x3808
/** Format code for PICT image files */
#define SUPPORTED_PLAYBACK_FORMAT_PICT 0x380A
/** Format code for PNG image files */
#define SUPPORTED_PLAYBACK_FORMAT_PNG 0x380B
/** Format code for TIFF image files */
#define SUPPORTED_PLAYBACK_FORMAT_TIFF 0x380D
/** Format code for JP2 files */
#define SUPPORTED_PLAYBACK_FORMAT_JP2 0x380F
/** Format code for JPX files */
#define SUPPORTED_PLAYBACK_FORMAT_JPX 0x3810
/** Format code for firmware files */
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED_FIRMWARE 0xB802
/** Format code for Windows image files */
#define SUPPORTED_PLAYBACK_FORMAT_WINDOWS_IMAGE_FORMAT 0xB881
/** Format code for undefined audio files files */
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED_AUDIO 0xB900
/** Format code for WMA audio files */
#define SUPPORTED_PLAYBACK_FORMAT_WMA 0xB901
/** Format code for OGG audio files */
#define SUPPORTED_PLAYBACK_FORMAT_OGG 0xB902
/** Format code for AAC audio files */
#define SUPPORTED_PLAYBACK_FORMAT_AAC 0xB903
/** Format code for Audible audio files */
#define SUPPORTED_PLAYBACK_FORMAT_AUDIBLE 0xB904
/** Format code for FLAC audio files */
#define SUPPORTED_PLAYBACK_FORMAT_FLAC 0xB906
/** Format code for undefined video files */
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED_VIDEO 0xB980
/** Format code for WMV video files */
#define SUPPORTED_PLAYBACK_FORMAT_WMV 0xB981
/** Format code for MP4 files */
#define SUPPORTED_PLAYBACK_FORMAT_MP4_CONTAINER 0xB982
/** Format code for MP2 files */
#define SUPPORTED_PLAYBACK_FORMAT_MP2 0xB983
/** Format code for 3GP files */
#define SUPPORTED_PLAYBACK_FORMAT_3GP_CONTAINER 0xB984
/** Format code for undefined collections */
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED_COLLECTION 0xBA00
/** Format code for multimedia albums */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01
/** Format code for image albums */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_IMAGE_ALBUM 0xBA02
/** Format code for audio albums */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AUDIO_ALBUM 0xBA03
/** Format code for video albums */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_VIDEO_ALBUM 0xBA04
/** Format code for abstract AV playlists */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AV_PLAYLIST 0xBA05
/** Format code for abstract audio playlists */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_AUDIO_PLAYLIST 0xBA09
/** Format code for abstract video playlists */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_VIDEO_PLAYLIST 0xBA0A
/** Format code for abstract mediacasts */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_MEDIACAST 0xBA0B
/** Format code for WPL playlist files */
#define SUPPORTED_PLAYBACK_FORMAT_WPL_PLAYLIST 0xBA10
/** Format code for M3u playlist files */
#define SUPPORTED_PLAYBACK_FORMAT_M3U_PLAYLIST 0xBA11
/** Format code for MPL playlist files */
#define SUPPORTED_PLAYBACK_FORMAT_MPL_PLAYLIST 0xBA12
/** Format code for ASX playlist files */
#define SUPPORTED_PLAYBACK_FORMAT_ASX_PLAYLIST 0xBA13
/** Format code for PLS playlist files */
#define SUPPORTED_PLAYBACK_FORMAT_PLS_PLAYLIST 0xBA14
/** Format code for undefined document files */
#define SUPPORTED_PLAYBACK_FORMAT_UNDEFINED_DOCUMENT 0xBA80
/** Format code for abstract documents */
#define SUPPORTED_PLAYBACK_FORMAT_ABSTRACT_DOCUMENT 0xBA81
/** Format code for XML documents */
#define SUPPORTED_PLAYBACK_FORMAT_XML_DOCUMENT 0xBA82
/** Format code for MS Word documents */
#define SUPPORTED_PLAYBACK_FORMAT_MS_WORD_DOCUMENT 0xBA83
/** Format code for MS Excel spreadsheets */
#define SUPPORTED_PLAYBACK_FORMAT_MS_EXCEL_SPREADSHEET 0xBA85
/** Format code for MS PowerPoint presentatiosn */
#define SUPPORTED_PLAYBACK_FORMAT_MS_POWERPOINT_PRESENTATION 0xBA86
#endif // _MTP_H
+884
View File
@@ -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);
}
}
+144
View File
@@ -0,0 +1,144 @@
/*
* 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++
*/
#ifndef MTP_MTPDATABASE_HPP
#define MTP_MTPDATABASE_HPP
#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 <map>
#include <string>
#include <deque>
#include "MtpDatabase.h"
#include "MtpDataPacket.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
#include "mtp.h"
class MyMtpDatabase : public MtpDatabase {
private:
int* getSupportedObjectProperties(int format);
static int FILE_PROPERTIES[10];
static int AUDIO_PROPERTIES[19];
static int VIDEO_PROPERTIES[15];
static int IMAGE_PROPERTIES[12];
static int ALL_PROPERTIES[25];
static int SUPPORTED_PLAYBACK_FORMATS[26];
int storagenum;
int count;
std::string lastfile;
std::map<int, MtpStorage*> storagemap;
void countDirs(std::string path);
int readParentDirs(std::string path, int storageID);
public:
MyMtpDatabase();
virtual ~MyMtpDatabase();
void createDB(MtpStorage* storage, MtpStorageID storageID);
virtual MtpObjectHandle beginSendObject(const char* path,
MtpObjectFormat format,
MtpObjectHandle parent,
MtpStorageID storage,
uint64_t size,
time_t modified);
virtual void endSendObject(const char* path,
MtpObjectHandle handle,
MtpObjectFormat format,
bool succeeded);
virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent);
virtual int getNumObjects(MtpStorageID storageID,
MtpObjectFormat format,
MtpObjectHandle parent);
// callee should delete[] the results from these
// results can be NULL
virtual MtpObjectFormatList* getSupportedPlaybackFormats();
virtual MtpObjectFormatList* getSupportedCaptureFormats();
virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
virtual MtpDevicePropertyList* getSupportedDeviceProperties();
virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet);
virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
MtpObjectProperty property,
MtpDataPacket& packet);
virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
MtpDataPacket& packet);
virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
MtpDataPacket& packet);
virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
uint32_t format, uint32_t property,
int groupCode, int depth,
MtpDataPacket& packet);
virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
MtpObjectInfo& info);
virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
MtpString& outFilePath,
int64_t& outFileLength,
MtpObjectFormat& outFormat);
virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
MtpObjectHandleList* references);
virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
MtpObjectFormat format);
virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
virtual void sessionStarted();
virtual void sessionEnded();
virtual void lockMutex();
virtual void unlockMutex();
};
#endif
+143
View File
@@ -0,0 +1,143 @@
/*
* 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 <vector>
#include <utils/threads.h>
#include "mtp_MtpServer.hpp"
#include "MtpServer.h"
#include "MtpStorage.h"
#include "MtpDebug.h"
#include <string>
void twmtp_MtpServer::start()
{
setup();
add_storage();
server->run();
}
void twmtp_MtpServer::set_storages(storages* mtpstorages) {
stores = mtpstorages;
}
void twmtp_MtpServer::setup()
{
#define USB_MTP_DEVICE "/dev/mtp_usb"
usePtp = false;
MyMtpDatabase* mtpdb = new MyMtpDatabase();
#ifdef USB_MTP_DEVICE
int fd = open(USB_MTP_DEVICE, O_RDWR);
#else
int fd = open("/dev/mtp_usb", O_RDWR);
#endif
if (fd >= 0) {
MTPD("fd: %d\n", fd);
server = new MtpServer(fd, mtpdb, usePtp, 0, 0664, 0775);
refserver = server;
MTPI("created new mtpserver object\n");
} else {
MTPE("could not open MTP driver, errno: %d", errno);
}
}
void twmtp_MtpServer::run()
{
MTPD("running in twmtp\n");
server->run();
}
void twmtp_MtpServer::cleanup()
{
android::Mutex sMutex;
android::Mutex::Autolock autoLock(sMutex);
if (server) {
delete server;
} else {
MTPD("server is null in cleanup");
}
}
void twmtp_MtpServer::send_object_added(int handle)
{
android::Mutex sMutex;
android::Mutex::Autolock autoLock(sMutex);
if (server)
server->sendObjectAdded(handle);
else
MTPD("server is null in send_object_added");
}
void twmtp_MtpServer::send_object_removed(int handle)
{
android::Mutex sMutex;
android::Mutex::Autolock autoLock(sMutex);
if (server)
server->sendObjectRemoved(handle);
else
MTPD("server is null in send_object_removed");
}
void twmtp_MtpServer::add_storage()
{
android::Mutex sMutex;
android::Mutex::Autolock autoLock(sMutex);
MTPI("adding internal storage\n");
for (unsigned int i = 0; i < stores->size(); ++i) {
std::string pathStr = stores->at(i)->mount;
if (!pathStr.empty()) {
std::string descriptionStr = stores->at(i)->display;
int storageID = stores->at(i)->mtpid;
long reserveSpace = 1;
bool removable = false;
long maxFileSize = 1000000000L;
if (descriptionStr != "") {
MtpStorage* storage = new MtpStorage(storageID, &pathStr[0], &descriptionStr[0], reserveSpace, removable, maxFileSize, refserver);
server->addStorage(storage);
}
}
}
}
void twmtp_MtpServer::remove_storage(int storageId)
{
android::Mutex sMutex;
android::Mutex::Autolock autoLock(sMutex);
if (server) {
MtpStorage* storage = server->getStorage(storageId);
if (storage) {
server->removeStorage(storage);
delete storage;
}
} else
MTPD("server is null in remove_storage");
}
+61
View File
@@ -0,0 +1,61 @@
/*
* 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++
*/
#ifndef MTP_MTPSERVER_HPP
#define MTP_MTPSERVER_HPP
#include <utils/Log.h>
#include <string>
#include <stdio.h>
#include <assert.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <utils/threads.h>
#include "MtpServer.h"
#include "MtpStorage.h"
#include "mtp_MtpDatabase.hpp"
typedef struct Storage {
std::string display;
std::string mount;
int mtpid;
} storage;
typedef std::vector<storage*> storages;
class twmtp_MtpServer {
public:
void start();
void setup();
void run();
void cleanup();
void send_object_added(int handle);
void send_object_removed(int handle);
void add_storage();
void remove_storage(int storageId);
void set_storages(storages* mtpstorages);
storages *stores;
private:
bool usePtp;
MtpServer* server;
MtpServer* refserver;
};
#endif
Executable
+139
View File
@@ -0,0 +1,139 @@
/*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*
* 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.
*/
#include <iostream>
#include <vector>
#include <sstream>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <libgen.h>
#include "btree.hpp"
#include "mtp.h"
#include "MtpDebug.h"
Node::Node() {
mtpid= -1;
path = "";
left = NULL;
right = NULL;
parent = NULL;
mtpparentid = 0;
}
void Node::setMtpid(int aMtpid) { mtpid = aMtpid; }
void Node::setPath(std::string aPath) { path = aPath; }
void Node::setLeft(Node* aLeft) { left = aLeft; }
void Node::setRight(Node* aRight) { right = aRight; }
void Node::setParent(Node* aParent) { parent = aParent; }
void Node::setMtpParentId(int id) {
mtpparentid = id;
MTPD("setting mtpparentid: %i on mtpid: %i\n", mtpparentid, mtpid);
}
int Node::Mtpid() { return mtpid; }
int Node::getMtpParentId() { return mtpparentid; }
std::string Node::getPath() { return path; }
Node* Node::Left() { return left; }
Node* Node::Right() { return right; }
Node* Node::Parent() { return parent; }
uint64_t Node::getIntProperty(uint64_t property) {
for (unsigned index = 0; index < mtpProp.size(); ++index) {
if (mtpProp[index].property == property)
return mtpProp[index].valueInt;
}
MTPE("Node::getIntProperty failed to find property %x, returning -1\n", (unsigned)property);
return -1;
}
void Node::addProperty(uint64_t property, uint64_t valueInt, std::string valueStr, int dataType) {
MTPD("adding str property: %lld, valueInt: %lld, valueStr: %s, dataType: %d\n", property, valueInt, valueStr.c_str(), dataType);
struct mtpProperty prop;
prop.property = property;
prop.valueInt = valueInt;
prop.valueStr = valueStr;
prop.dataType = dataType;
mtpProp.push_back(prop);
}
void Node::updateProperty(uint64_t property, uint64_t valueInt, std::string valueStr, int dataType) {
for (unsigned i = 0; i < mtpProp.size(); i++) {
if (mtpProp[i].property == property) {
mtpProp[i].valueInt = valueInt;
mtpProp[i].valueStr = valueStr;
mtpProp[i].dataType = dataType;
return;
}
}
addProperty(property, valueInt, valueStr, dataType);
}
std::vector<Node::mtpProperty>& Node::getMtpProps() {
return mtpProp;
}
void Node::addProperties(int storageID, int parent_object) {
struct stat st;
int mFormat = 0;
uint64_t puid;
std::string mtpidStr = static_cast<std::ostringstream*>( &(std::ostringstream() << mtpid) )->str();
std::string storageIDStr = static_cast<std::ostringstream*>( &(std::ostringstream() << storageID) )->str();
std::string puidStr = storageIDStr + mtpidStr;
if ( ! (std::istringstream(puidStr) >> puid) ) puid = 0;
stat(getPath().c_str(), &st);
std::string mtimeStr = static_cast<std::ostringstream*>( &(std::ostringstream() << st.st_mtime) )->str();
std::string atimeStr = static_cast<std::ostringstream*>( &(std::ostringstream() << st.st_atime) )->str();
if (S_ISDIR(st.st_mode)) {
mFormat = MTP_FORMAT_ASSOCIATION; // folder
}
else {
mFormat = MTP_FORMAT_UNDEFINED; // file
}
addProperty(MTP_PROPERTY_STORAGE_ID, storageID, "", MTP_TYPE_UINT32);
addProperty(MTP_PROPERTY_OBJECT_FORMAT, mFormat, "", MTP_TYPE_UINT16);
addProperty(MTP_PROPERTY_PROTECTION_STATUS, 0, "", MTP_TYPE_UINT16);
addProperty(MTP_PROPERTY_OBJECT_SIZE, st.st_size, "", MTP_TYPE_UINT64);
addProperty(MTP_PROPERTY_OBJECT_FILE_NAME, 0, basename(getPath().c_str()), MTP_TYPE_STR);
MTPD("mtpid: %i, filename: '%s', parent object: %i\n", mtpid, basename(getPath().c_str()), parent_object);
addProperty(MTP_PROPERTY_DATE_MODIFIED, 0, mtimeStr, MTP_TYPE_STR);
addProperty(MTP_PROPERTY_PARENT_OBJECT, parent_object, "", MTP_TYPE_UINT32);
addProperty(MTP_PROPERTY_PERSISTENT_UID, puid, "", MTP_TYPE_UINT128);
addProperty(MTP_PROPERTY_NAME, 0, basename(getPath().c_str()), MTP_TYPE_STR);
addProperty(MTP_PROPERTY_DISPLAY_NAME, 0, basename(getPath().c_str()), MTP_TYPE_STR);
addProperty(MTP_PROPERTY_DATE_ADDED, 0, atimeStr, MTP_TYPE_STR);
addProperty(MTP_PROPERTY_DESCRIPTION, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_ARTIST, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_ALBUM_NAME, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_ALBUM_ARTIST, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_TRACK, 0, "", MTP_TYPE_UINT16);
addProperty(MTP_PROPERTY_ORIGINAL_RELEASE_DATE, 0, "00101T000000", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_DURATION, 0, "", MTP_TYPE_UINT32);
addProperty(MTP_PROPERTY_GENRE, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_COMPOSER, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_ARTIST, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_ALBUM_NAME, 0, "", MTP_TYPE_STR);
addProperty(MTP_PROPERTY_DURATION, 0, "", MTP_TYPE_UINT32);
addProperty(MTP_PROPERTY_DESCRIPTION, 0, "", MTP_TYPE_STR);
}
+98
View File
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*
* 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.
*/
#include <string>
#include <fcntl.h>
#include <sys/wait.h>
#include <pthread.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include "MtpTypes.h"
#include "MtpPacket.h"
#include "MtpDataPacket.h"
#include "MtpDatabase.h"
#include "MtpRequestPacket.h"
#include "MtpResponsePacket.h"
#include "mtp_MtpDatabase.hpp"
#include "mtp_MtpServer.hpp"
#include "twrpMtp.hpp"
#include "MtpDebug.h"
#ifdef TWRPMTP
static void usage(std::string prg) {
printf("Usage: %s <OPTIONS>\n", prg.c_str());
printf("Options:\n");
printf("\t-h, --help\t\tShow Usage\n");
printf("\t-s1, --storage1 /path/to/dir\t\tDestination to first storage directory\n");
printf("\t-s2, --storage2 /path/to/dir\t\tDestination to first storage directory\n");
printf("\t-sN, --storageN /path/to/dir\t\tDestination to first storage directory\n");
}
int main(int argc, char* argv[]) {
printf("argc: %d\n", argc);
if (argc < 2) {
usage(argv[0]);
return 1;
}
std::vector <std::string> storages;
for (int i = 1; i < argc; ++i) {
std::string arg = argv[i];
if ((arg == "-h") || (arg == "--help")) {
usage(argv[0]);
}
else {
storages.push_back(arg);
}
}
printf("starting\n");
twmtp_MtpServer* mtp = new twmtp_MtpServer();
mtp->set_storages(storages);
mtp->start();
return 0;
}
#endif //def TWRPMTP
twrpMtp::twrpMtp() {
mtpstorages = new storages;
}
int twrpMtp::start(void) {
MTPI("Starting MTP\n");
twmtp_MtpServer *mtp = new twmtp_MtpServer();
mtp->set_storages(mtpstorages);
mtp->start();
return 0;
}
pthread_t twrpMtp::runserver(void) {
pthread_t thread;
ThreadPtr mtpptr = &twrpMtp::start;
PThreadPtr p = *(PThreadPtr*)&mtpptr;
pthread_create(&thread, NULL, p, this);
return thread;
}
void twrpMtp::addStorage(std::string display, std::string path, int mtpid) {
s = new storage;
s->display = display;
s->mount = path;
s->mtpid = mtpid;
MTPD("twrpMtp mtpid: %d\n", s->mtpid);
mtpstorages->push_back(s);
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
*
* 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.
*/
#ifndef TWRPMTP_HPP
#define TWRPMTP_HPP
#include <fcntl.h>
#include <utils/Errors.h>
#include <utils/threads.h>
#include <string>
#include <vector>
#include <pthread.h>
#include "MtpTypes.h"
#include "MtpPacket.h"
#include "MtpDataPacket.h"
#include "MtpDatabase.h"
#include "MtpRequestPacket.h"
#include "MtpResponsePacket.h"
#include "mtp_MtpDatabase.hpp"
class twrpMtp {
public:
twrpMtp();
pthread_t runserver(void);
void addStorage(std::string display, std::string path, int mtpid);
private:
int start(void);
typedef int (twrpMtp::*ThreadPtr)(void);
typedef void* (*PThreadPtr)(void *);
storages *mtpstorages;
storage *s;
};
#endif
+28 -6
View File
@@ -107,7 +107,8 @@ static struct flag_list mount_flags[] = {
{ 0, 0 },
};
TWPartition::TWPartition(void) {
TWPartition::TWPartition(int *id) {
initmtpid = id;
Can_Be_Mounted = false;
Can_Be_Wiped = false;
Can_Be_Backed_Up = false;
@@ -430,6 +431,12 @@ bool TWPartition::Process_Fstab_Line(string Line, bool Display_Error) {
}
}
// Generate MTP ID
if (Is_Storage) {
(*initmtpid)++;
mtpid = *initmtpid;
}
// Process any custom flags
if (Flags.size() > 0)
Process_Flags(Flags, Display_Error);
@@ -1051,6 +1058,9 @@ bool TWPartition::UnMount(bool Display_Error) {
if (never_unmount_system == 1 && Mount_Point == "/system")
return true; // Never unmount system if you're not supposed to unmount it
if (Is_Storage)
TWFunc::Toggle_MTP(false);
#ifdef TW_INCLUDE_CRYPTO_SAMSUNG
if (EcryptFS_Password.size() > 0) {
if (unmount_ecryptfs_drive(Mount_Point.c_str()) != 0) {
@@ -1074,15 +1084,16 @@ bool TWPartition::UnMount(bool Display_Error) {
else
LOGINFO("Unable to unmount '%s'\n", Mount_Point.c_str());
return false;
} else
} else {
return true;
}
} else {
return true;
}
}
bool TWPartition::Wipe(string New_File_System) {
bool wiped = false, update_crypt = false, recreate_media = true;
bool wiped = false, update_crypt = false, recreate_media = true, mtp_toggle = true;
int check;
string Layout_Filename = Mount_Point + "/.layout_version";
@@ -1109,8 +1120,8 @@ bool TWPartition::Wipe(string New_File_System) {
if (Has_Data_Media && Current_File_System == New_File_System) {
wiped = Wipe_Data_Without_Wiping_Media();
recreate_media = false;
mtp_toggle = false;
} else {
DataManager::GetValue(TW_RM_RF_VAR, check);
if (check || Use_Rm_Rf)
@@ -1128,6 +1139,9 @@ bool TWPartition::Wipe(string New_File_System) {
else if (New_File_System == "f2fs")
wiped = Wipe_F2FS();
else {
if (Is_Storage) {
TWFunc::Toggle_MTP(true);
}
LOGERR("Unable to wipe '%s' -- unknown file system '%s'\n", Mount_Point.c_str(), New_File_System.c_str());
unlink("/.layout_version");
return false;
@@ -1169,6 +1183,9 @@ bool TWPartition::Wipe(string New_File_System) {
Recreate_Media_Folder();
}
}
if (Is_Storage && mtp_toggle) {
TWFunc::Toggle_MTP(true);
}
return wiped;
}
@@ -1417,6 +1434,8 @@ bool TWPartition::Wipe_Encryption() {
Decrypted_Block_Device = "";
Is_Decrypted = false;
Is_Encrypted = false;
Find_Actual_Block_Device();
bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
if (Wipe(Fstab_File_System)) {
Has_Data_Media = Save_Data_Media;
if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
@@ -1425,6 +1444,7 @@ bool TWPartition::Wipe_Encryption() {
#ifndef TW_OEM_BUILD
gui_print("You may need to reboot recovery to be able to use /data again.\n");
#endif
TWFunc::Toggle_MTP(mtp_was_enabled);
return true;
} else {
Has_Data_Media = Save_Data_Media;
@@ -1632,6 +1652,8 @@ bool TWPartition::Wipe_MTD() {
}
bool TWPartition::Wipe_RMRF() {
if (Is_Storage)
TWFunc::Toggle_MTP(false);
if (!Mount(true))
return false;
@@ -2018,9 +2040,9 @@ bool TWPartition::Update_Size(bool Display_Error) {
}
void TWPartition::Find_Actual_Block_Device(void) {
if (Is_Decrypted) {
if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
Actual_Block_Device = Decrypted_Block_Device;
if (TWFunc::Path_Exists(Primary_Block_Device))
if (TWFunc::Path_Exists(Decrypted_Block_Device))
Is_Present = true;
} else if (TWFunc::Path_Exists(Primary_Block_Device)) {
Is_Present = true;
+104 -11
View File
@@ -38,6 +38,11 @@
#include "twrpDigest.hpp"
#include "twrpDU.hpp"
#ifdef TW_HAS_MTP
#include "mtp/mtp_MtpServer.hpp"
#include "mtp/twrpMtp.hpp"
#endif
extern "C" {
#include "cutils/properties.h"
}
@@ -51,6 +56,8 @@ extern "C" {
#endif
TWPartitionManager::TWPartitionManager(void) {
mtpid = 100;
mtp_was_enabled = false;
}
int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error) {
@@ -71,8 +78,7 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error)
if (fstab_line[strlen(fstab_line) - 1] != '\n')
fstab_line[strlen(fstab_line)] = '\n';
TWPartition* partition = new TWPartition();
TWPartition* partition = new TWPartition(&mtpid);
string line = fstab_line;
memset(fstab_line, 0, sizeof(fstab_line));
@@ -1297,15 +1303,25 @@ int TWPartitionManager::Wipe_Media_From_Data(void) {
return false;
gui_print("Wiping internal storage -- /data/media...\n");
mtp_was_enabled = TWFunc::Toggle_MTP(false);
TWFunc::removeDir("/data/media", false);
if (mkdir("/data/media", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0)
return -1;
if (mkdir("/data/media", S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP) != 0) {
if (mtp_was_enabled) {
if (!Enable_MTP())
Disable_MTP();
}
return false;
}
if (dat->Has_Data_Media) {
dat->Recreate_Media_Folder();
// Unmount and remount - slightly hackish way to ensure that the "/sdcard" folder is still mounted properly after wiping
dat->UnMount(false);
dat->Mount(false);
}
if (mtp_was_enabled) {
if (!Enable_MTP())
Disable_MTP();
}
return true;
} else {
LOGERR("Unable to locate /data.\n");
@@ -1735,20 +1751,22 @@ int TWPartitionManager::usb_storage_enable(void) {
if (TWFunc::Path_Exists(lun_file))
has_multiple_lun = true;
}
mtp_was_enabled = TWFunc::Toggle_MTP(false);
if (!has_multiple_lun) {
LOGINFO("Device doesn't have multiple lun files, mount current storage\n");
sprintf(lun_file, CUSTOM_LUN_FILE, 0);
if (TWFunc::Get_Root_Path(DataManager::GetCurrentStoragePath()) == "/data") {
TWPartition* Mount = Find_Next_Storage("", "/data");
if (Mount) {
if (!Open_Lun_File(Mount->Mount_Point, lun_file))
return false;
if (!Open_Lun_File(Mount->Mount_Point, lun_file)) {
goto error_handle;
}
} else {
LOGERR("Unable to find storage partition to mount to USB\n");
return false;
goto error_handle;
}
} else if (!Open_Lun_File(DataManager::GetCurrentStoragePath(), lun_file)) {
return false;
goto error_handle;
}
} else {
LOGINFO("Device has multiple lun files\n");
@@ -1757,8 +1775,9 @@ int TWPartitionManager::usb_storage_enable(void) {
sprintf(lun_file, CUSTOM_LUN_FILE, 0);
Mount1 = Find_Next_Storage("", "/data");
if (Mount1) {
if (!Open_Lun_File(Mount1->Mount_Point, lun_file))
return false;
if (!Open_Lun_File(Mount1->Mount_Point, lun_file)) {
goto error_handle;
}
sprintf(lun_file, CUSTOM_LUN_FILE, 1);
Mount2 = Find_Next_Storage(Mount1->Mount_Point, "/data");
if (Mount2) {
@@ -1766,11 +1785,16 @@ int TWPartitionManager::usb_storage_enable(void) {
}
} else {
LOGERR("Unable to find storage partition to mount to USB\n");
return false;
goto error_handle;
}
}
property_set("sys.storage.ums_enabled", "1");
return true;
error_handle:
if (mtp_was_enabled)
if (!Enable_MTP())
Disable_MTP();
return false;
}
int TWPartitionManager::usb_storage_disable(void) {
@@ -1789,6 +1813,9 @@ int TWPartitionManager::usb_storage_disable(void) {
Update_System_Details();
UnMount_Main_Partitions();
property_set("sys.storage.ums_enabled", "0");
if (mtp_was_enabled)
if (!Enable_MTP())
Disable_MTP();
if (ret < 0 && index == 0) {
LOGERR("Unable to write to ums lunfile '%s'.", lun_file);
return false;
@@ -2123,3 +2150,69 @@ TWPartition *TWPartitionManager::Get_Default_Storage_Partition()
}
return res;
}
bool TWPartitionManager::Enable_MTP(void) {
#ifdef TW_HAS_MTP
if (mtpthread) {
LOGERR("MTP already enabled\n");
return true;
}
//Launch MTP Responder
LOGINFO("Starting MTP\n");
char vendor[PROPERTY_VALUE_MAX];
char product[PROPERTY_VALUE_MAX];
int count = 0;
property_set("sys.usb.config", "none");
property_get("usb.vendor", vendor, "18D1");
property_get("usb.product.mtpadb", product, "4EE2");
string vendorstr = vendor;
string productstr = product;
TWFunc::write_file("/sys/class/android_usb/android0/idVendor", vendorstr);
TWFunc::write_file("/sys/class/android_usb/android0/idProduct", productstr);
property_set("sys.usb.config", "mtp,adb");
std::vector<TWPartition*>::iterator iter;
twrpMtp *mtp = new twrpMtp();
for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
if ((*iter)->Is_Storage && (*iter)->Is_Present && (*iter)->Mount(false)) {
printf("twrp mtpid: %d\n", (*iter)->mtpid);
mtp->addStorage((*iter)->Storage_Name, (*iter)->Storage_Path, (*iter)->mtpid);
count++;
}
}
if (count) {
mtpthread = mtp->runserver();
DataManager::SetValue("tw_mtp_enabled", 1);
return true;
}
LOGERR("No valid storage partitions found for MTP.\n");
#else
LOGERR("MTP support not included\n");
#endif
DataManager::SetValue("tw_mtp_enabled", 0);
return false;
}
bool TWPartitionManager::Disable_MTP(void) {
#ifdef TW_HAS_MTP
char vendor[PROPERTY_VALUE_MAX];
char product[PROPERTY_VALUE_MAX];
property_set("sys.usb.config", "none");
property_get("usb.vendor", vendor, "18D1");
property_get("usb.product.adb", product, "D002");
string vendorstr = vendor;
string productstr = product;
TWFunc::write_file("/sys/class/android_usb/android0/idVendor", vendorstr);
TWFunc::write_file("/sys/class/android_usb/android0/idProduct", productstr);
if (mtpthread) {
pthread_kill(mtpthread, 0);
mtpthread = NULL;
}
property_set("sys.usb.config", "adb");
DataManager::SetValue("tw_mtp_enabled", 0);
return true;
#else
LOGERR("MTP support not included\n");
DataManager::SetValue("tw_mtp_enabled", 0);
return false;
#endif
}
+9 -2
View File
@@ -45,7 +45,7 @@ public:
};
public:
TWPartition();
TWPartition(int *id);
virtual ~TWPartition();
public:
@@ -72,6 +72,7 @@ public:
string Current_File_System; // Current file system
string Actual_Block_Device; // Actual block device (one of primary, alternate, or decrypted)
string MTD_Name; // Name of the partition for MTD devices
bool Is_Present; // Indicates if the partition is currently present as a block device
private:
bool Process_Fstab_Line(string Line, bool Display_Error); // Processes a fstab line
@@ -127,8 +128,9 @@ private:
string Alternate_Block_Device; // Alternate block device (e.g. /dev/block/mmcblk1)
string Decrypted_Block_Device; // Decrypted block device available after decryption
bool Removable; // Indicates if this partition is removable -- affects how often we check overall size, if present, etc.
bool Is_Present; // Indicates if the partition is currently present as a block device
int Length; // Used by make_ext4fs to leave free space at the end of the partition block for things like a crypto footer
int *initmtpid; // Initial MTP ID
int mtpid; // Store MTP ID
unsigned long long Size; // Overall size of the partition
unsigned long long Used; // Overall used space
unsigned long long Free; // Overall free space
@@ -224,6 +226,8 @@ public:
void Get_Partition_List(string ListType, std::vector<PartitionList> *Partition_List);
int Fstab_Processed(); // Indicates if the fstab has been processed or not
void Output_Storage_Fstab(); // Creates a /cache/recovery/storage.fstab file with a list of all potential storage locations for app use
bool Enable_MTP(); // Enables MTP
bool Disable_MTP(); // Disables MTP
private:
void Setup_Settings_Storage_Partition(TWPartition* Part); // Sets up settings storage
@@ -234,6 +238,9 @@ private:
void Output_Partition(TWPartition* Part);
TWPartition* Find_Next_Storage(string Path, string Exclude);
int Open_Lun_File(string Partition_Path, string Lun_File);
int mtpid;
pthread_t mtpthread;
bool mtp_was_enabled;
private:
std::vector<TWPartition*> Partitions; // Vector list of all partitions
+10
View File
@@ -26,8 +26,13 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/e2fsck
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/mke2fs
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/tune2fs
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/linker
#RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/twrpmtp
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libc.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcutils.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcorkscrew.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libusbhost.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libgccdemangle.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libutils.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libdl.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_blkid.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext2_com_err.so
@@ -53,6 +58,11 @@ RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libstlport.so
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/toolbox
ifneq ($(TW_OEM_BUILD),true)
RELINK_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/sbin/twrp
else
TW_EXCLUDE_MTP := true
endif
ifneq ($(TW_EXCLUDE_MTP), true)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libtwrpmtp.so
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libext4_utils.so
+18
View File
@@ -1260,4 +1260,22 @@ int TWFunc::Set_Brightness(std::string brightness_value)
return -1;
}
bool TWFunc::Toggle_MTP(bool enable) {
#ifdef TW_HAS_MTP
static int was_enabled = false;
if (enable && was_enabled) {
if (!PartitionManager.Enable_MTP())
PartitionManager.Disable_MTP();
} else {
was_enabled = DataManager::GetIntValue("tw_mtp_enabled");
PartitionManager.Disable_MTP();
usleep(500);
}
return was_enabled;
#else
return false;
#endif
}
#endif // ndef BUILD_TWRPTAR_MAIN
+1
View File
@@ -85,6 +85,7 @@ public:
static std::vector<std::string> Split_String(const std::string& str, const std::string& delimiter, bool removeEmpty = true); // Splits string by delimiter
static bool Create_Dir_Recursive(const std::string& path, mode_t mode = 0755, uid_t uid = -1, gid_t gid = -1); // Create directory and it's parents, if they don't exist. mode, uid and gid are set to all _newly_ created folders. If whole path exists, do nothing.
static int Set_Brightness(std::string brightness_value); // Well, you can read, it does what it says, passing return int from TWFunc::Write_File ;)
static bool Toggle_MTP(bool enable); // Disables MTP if enable is false and re-enables MTP if enable is true and it was enabled the last time it was toggled off
private:
static void Copy_Log(string Source, string Destination);
+19
View File
@@ -82,6 +82,8 @@ int main(int argc, char **argv) {
crash_counter = atoi(crash_prop_val) + 1;
snprintf(crash_prop_val, sizeof(crash_prop_val), "%d", crash_counter);
property_set("twrp.crash_counter", crash_prop_val);
property_set("ro.twrp.boot", "1");
property_set("ro.twrp.version", TW_VERSION_STR);
time_t StartupTime = time(NULL);
printf("Starting TWRP %s on %s", TW_VERSION_STR, ctime(&StartupTime));
@@ -279,6 +281,23 @@ int main(int argc, char **argv) {
OpenRecoveryScript::Run_OpenRecoveryScript();
}
// Enable MTP?
if (DataManager::GetIntValue(TW_IS_ENCRYPTED) != 0) {
if (DataManager::GetIntValue(TW_IS_DECRYPTED) != 0 && DataManager::GetIntValue("tw_mtp_enabled") == 1) {
LOGINFO("Enabling MTP during startup\n");
if (!PartitionManager.Enable_MTP())
PartitionManager.Disable_MTP();
else
gui_print("MTP Enabled\n");
}
} else if (DataManager::GetIntValue("tw_mtp_enabled") == 1) {
LOGINFO("Enabling MTP during startup\n");
if (!PartitionManager.Enable_MTP())
PartitionManager.Disable_MTP();
else
gui_print("MTP Enabled\n");
}
// Launch the main GUI
gui_start();
+1 -1
View File
@@ -17,7 +17,7 @@
#ifndef _VARIABLES_HEADER_
#define _VARIABLES_HEADER_
#define TW_VERSION_STR "2.7.1.0"
#define TW_VERSION_STR "2.8.0.0"
#define TW_USE_COMPRESSION_VAR "tw_use_compression"
#define TW_FILENAME "tw_filename"