add mtp responder to TWRP.
Big thanks to Dees_Troy for helping with the implementation. Change-Id: I6c9c522b9c9de5dc139e2ecb0141008182ba07f0
This commit is contained in:
+9
-4
@@ -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 :=
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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%" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
Executable
+488
@@ -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;
|
||||
}
|
||||
|
||||
Executable
+123
@@ -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
|
||||
Executable
+115
@@ -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
|
||||
Executable
+419
@@ -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
@@ -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
|
||||
Executable
+833
@@ -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;
|
||||
}
|
||||
}
|
||||
Executable
+116
@@ -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
|
||||
Executable
+94
@@ -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);
|
||||
}
|
||||
|
||||
Executable
+54
@@ -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
|
||||
Executable
+68
@@ -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
|
||||
|
||||
|
||||
Executable
+46
@@ -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
|
||||
Executable
+105
@@ -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);
|
||||
}
|
||||
|
||||
Executable
+60
@@ -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
|
||||
Executable
+164
@@ -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
|
||||
|
||||
Executable
+72
@@ -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
|
||||
Executable
+531
@@ -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]);
|
||||
}
|
||||
|
||||
Executable
+114
@@ -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
|
||||
Executable
+61
@@ -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
|
||||
|
||||
Executable
+49
@@ -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
|
||||
Executable
+58
@@ -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
|
||||
|
||||
|
||||
Executable
+48
@@ -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
|
||||
Executable
+1337
File diff suppressed because it is too large
Load Diff
Executable
+155
@@ -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
|
||||
Executable
+941
@@ -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);
|
||||
}
|
||||
Executable
+103
@@ -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
|
||||
Executable
+69
@@ -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);
|
||||
}
|
||||
|
||||
Executable
+49
@@ -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
|
||||
Executable
+167
@@ -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);
|
||||
}
|
||||
|
||||
Executable
+55
@@ -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
@@ -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
|
||||
Executable
+78
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
Executable
+884
@@ -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);
|
||||
}
|
||||
}
|
||||
Executable
+144
@@ -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
|
||||
Executable
+143
@@ -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");
|
||||
}
|
||||
Executable
+61
@@ -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
@@ -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);
|
||||
}
|
||||
Executable
+98
@@ -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);
|
||||
}
|
||||
Executable
+46
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user