MTP: host support for retrieving device property descriptors

Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2010-06-05 22:45:01 -04:00
parent 7c5ded5d36
commit 90f4873446
11 changed files with 339 additions and 24 deletions

View File

@@ -61,6 +61,7 @@ LOCAL_SRC_FILES:= \
MtpDeviceInfo.cpp \
MtpObjectInfo.cpp \
MtpPacket.cpp \
MtpProperty.cpp \
MtpRequestPacket.cpp \
MtpResponsePacket.cpp \
MtpStorageInfo.cpp \

View File

@@ -70,6 +70,13 @@ uint64_t MtpDataPacket::getUInt64() {
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);
@@ -217,6 +224,20 @@ void MtpDataPacket::putUInt64(uint64_t value) {
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::putAInt8(const int8_t* values, int count) {
putUInt32(count);
for (int i = 0; i < count; i++)

View File

@@ -44,6 +44,8 @@ public:
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();
@@ -63,6 +65,8 @@ public:
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 putAInt8(const int8_t* values, int count);
void putAUInt8(const uint8_t* values, int count);

View File

@@ -14,6 +14,9 @@
* limitations under the License.
*/
#define LOG_TAG "MtpDevice"
#include "utils/Log.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
@@ -28,6 +31,7 @@
#include "MtpDebug.h"
#include "MtpDeviceInfo.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpStorageInfo.h"
#include "MtpStringBuffer.h"
@@ -50,6 +54,8 @@ MtpDevice::MtpDevice(struct usb_device* device, int interface,
MtpDevice::~MtpDevice() {
close();
for (int i = 0; i < mDeviceProperties.size(); i++)
delete mDeviceProperties[i];
}
void MtpDevice::initialize() {
@@ -57,6 +63,18 @@ void MtpDevice::initialize() {
mDeviceInfo = getDeviceInfo();
if (mDeviceInfo) {
mDeviceInfo->print();
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) {
property->print();
mDeviceProperties.push(property);
}
}
}
}
}
@@ -76,7 +94,6 @@ const char* MtpDevice::getDeviceName() {
}
bool MtpDevice::openSession() {
printf("openSession\n");
mSessionID = 0;
mTransactionID = 0;
MtpSessionID newSession = 1;
@@ -107,7 +124,6 @@ MtpDeviceInfo* MtpDevice::getDeviceInfo() {
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
printf("getDeviceInfo returned %04X\n", ret);
if (ret == MTP_RESPONSE_OK) {
MtpDeviceInfo* info = new MtpDeviceInfo;
info->read(mData);
@@ -137,7 +153,6 @@ MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
printf("getStorageInfo returned %04X\n", ret);
if (ret == MTP_RESPONSE_OK) {
MtpStorageInfo* info = new MtpStorageInfo(storageID);
info->read(mData);
@@ -157,7 +172,6 @@ MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
printf("getObjectHandles returned %04X\n", ret);
if (ret == MTP_RESPONSE_OK) {
return mData.getAUInt32();
}
@@ -172,7 +186,6 @@ MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
if (!readData())
return NULL;
MtpResponseCode ret = readResponse();
printf("getObjectInfo returned %04X\n", ret);
if (ret == MTP_RESPONSE_OK) {
MtpObjectInfo* info = new MtpObjectInfo(handle);
info->read(mData);
@@ -181,8 +194,25 @@ printf("getObjectInfo returned %04X\n", ret);
return NULL;
}
MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
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;
}
bool MtpDevice::sendRequest(MtpOperationCode operation) {
printf("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
LOGD("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
mRequest.setOperationCode(operation);
if (mTransactionID > 0)
mRequest.setTransactionID(mTransactionID++);
@@ -192,7 +222,7 @@ bool MtpDevice::sendRequest(MtpOperationCode operation) {
}
bool MtpDevice::sendData(MtpOperationCode operation) {
printf("sendData\n");
LOGD("sendData\n");
mData.setOperationCode(mRequest.getOperationCode());
mData.setTransactionID(mRequest.getTransactionID());
int ret = mData.write(mEndpointOut);
@@ -203,26 +233,26 @@ bool MtpDevice::sendData(MtpOperationCode operation) {
bool MtpDevice::readData() {
mData.reset();
int ret = mData.read(mEndpointIn);
printf("readData returned %d\n", ret);
LOGD("readData returned %d\n", ret);
if (ret >= MTP_CONTAINER_HEADER_SIZE) {
mData.dump();
return true;
}
else {
printf("readResponse failed\n");
LOGD("readResponse failed\n");
return false;
}
}
MtpResponseCode MtpDevice::readResponse() {
printf("readResponse\n");
LOGD("readResponse\n");
int ret = mResponse.read(mEndpointIn);
if (ret >= MTP_CONTAINER_HEADER_SIZE) {
mResponse.dump();
return mResponse.getResponseCode();
}
else {
printf("readResponse failed\n");
LOGD("readResponse failed\n");
return -1;
}
}

View File

@@ -36,6 +36,7 @@ private:
struct usb_endpoint* mEndpointOut;
struct usb_endpoint* mEndpointIntr;
MtpDeviceInfo* mDeviceInfo;
MtpPropertyList mDeviceProperties;
// a unique ID for the device
int mID;
@@ -70,6 +71,8 @@ public:
MtpObjectHandleList* getObjectHandles(MtpStorageID storageID, MtpObjectFormat format, MtpObjectHandle parent);
MtpObjectInfo* getObjectInfo(MtpObjectHandle handle);
MtpProperty* getDevicePropDesc(MtpDeviceProperty code);
private:
bool sendRequest(MtpOperationCode operation);
bool sendData(MtpOperationCode operation);

View File

@@ -14,7 +14,8 @@
* limitations under the License.
*/
#include <stdlib.h>
#define LOG_TAG "MtpDeviceInfo"
#include "utils/Log.h"
#include "MtpDataPacket.h"
#include "MtpDeviceInfo.h"
@@ -87,9 +88,9 @@ void MtpDeviceInfo::read(MtpDataPacket& packet) {
}
void MtpDeviceInfo::print() {
printf("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
LOGD("Device Info:\n\tmStandardVersion: %d\n\tmVendorExtensionID: %d\n\tmVendorExtensionVersiony: %d\n",
mStandardVersion, mVendorExtensionID, mVendorExtensionVersion);
printf("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
LOGD("\tmVendorExtensionDesc: %s\n\tmFunctionalCode: %d\n\tmManufacturer: %s\n\tmModel: %s\n\tmVersion: %s\n\tmSerial: %s\n",
mVendorExtensionDesc, mFunctionalCode, mManufacturer, mModel, mVersion, mSerial);
}

View File

@@ -14,7 +14,8 @@
* limitations under the License.
*/
#include <stdlib.h>
#define LOG_TAG "MtpObjectInfo"
#include "utils/Log.h"
#include "MtpDataPacket.h"
#include "MtpObjectInfo.h"
@@ -90,7 +91,7 @@ void MtpObjectInfo::read(MtpDataPacket& packet) {
}
void MtpObjectInfo::print() {
printf("MtpObject Info %08X: %s\n", mHandle, mName);
LOGD("MtpObject Info %08X: %s\n", mHandle, mName);
}
} // namespace android

161
media/mtp/MtpProperty.cpp Normal file
View File

@@ -0,0 +1,161 @@
/*
* 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.
*/
#define LOG_TAG "MtpProperty"
#include "utils/Log.h"
#include "MtpDataPacket.h"
#include "MtpProperty.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"
namespace android {
MtpProperty::MtpProperty()
: mCode(0),
mType(0),
mWriteable(false),
mDefaultArrayLength(0),
mDefaultArrayValues(NULL),
mCurrentArrayLength(0),
mCurrentArrayValues(NULL),
mFormFlag(kFormNone),
mEnumLength(0),
mEnumValues(NULL)
{
mDefaultValue.str = NULL;
mCurrentValue.str = NULL;
mMinimumValue.str = NULL;
mMaximumValue.str = NULL;
}
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) {
MtpStringBuffer string;
mCode = packet.getUInt16();
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);
mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
break;
default:
readValue(packet, mDefaultValue);
readValue(packet, mCurrentValue);
}
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::print() {
LOGD("MtpProperty %04X\n", mCode);
LOGD(" type %04X\n", mType);
LOGD(" writeable %s\n", (mWriteable ? "true" : "false"));
}
void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
switch (mType) {
case MTP_TYPE_INT8:
value.i8 = packet.getInt8();
break;
case MTP_TYPE_UINT8:
value.u8 = packet.getUInt8();
break;
case MTP_TYPE_INT16:
value.i16 = packet.getInt16();
break;
case MTP_TYPE_UINT16:
value.u16 = packet.getUInt16();
break;
case MTP_TYPE_INT32:
value.i32 = packet.getInt32();
break;
case MTP_TYPE_UINT32:
value.u32 = packet.getUInt32();
break;
case MTP_TYPE_INT64:
value.i64 = packet.getInt64();
break;
case MTP_TYPE_UINT64:
value.u64 = packet.getUInt64();
break;
case MTP_TYPE_INT128:
packet.getInt128(value.i128);
break;
case MTP_TYPE_UINT128:
packet.getUInt128(value.u128);
break;
default:
fprintf(stderr, "unknown type %d in MtpProperty::readValue\n", 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;
}
} // namespace android

71
media/mtp/MtpProperty.h Normal file
View File

@@ -0,0 +1,71 @@
/*
* 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.
*/
#ifndef _MTP_PROPERTY_H
#define _MTP_PROPERTY_H
#include "MtpTypes.h"
namespace android {
class MtpDataPacket;
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,
};
uint8_t mFormFlag;
// for range form
MtpPropertyValue mMinimumValue;
MtpPropertyValue mMaximumValue;
MtpPropertyValue mStepSize;
// for enum form
int mEnumLength;
MtpPropertyValue* mEnumValues;
public:
MtpProperty();
virtual ~MtpProperty();
void read(MtpDataPacket& packet);
void print();
private:
void readValue(MtpDataPacket& packet, MtpPropertyValue& value);
MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);
};
}; // namespace android
#endif // _MTP_PROPERTY_H

View File

@@ -14,7 +14,8 @@
* limitations under the License.
*/
#include <stdlib.h>
#define LOG_TAG "MtpStorageInfo"
#include "utils/Log.h"
#include "MtpDataPacket.h"
#include "MtpStorageInfo.h"
@@ -60,11 +61,11 @@ void MtpStorageInfo::read(MtpDataPacket& packet) {
}
void MtpStorageInfo::print() {
printf("Storage Info %08X:\n\tmStorageType: %d\n\tmFileSystemType: %d\n\tmAccessCapability: %d\n",
LOGD("Storage Info %08X:\n\tmStorageType: %d\n\tmFileSystemType: %d\n\tmAccessCapability: %d\n",
mStorageID, mStorageType, mFileSystemType, mAccessCapability);
printf("\tmMaxCapacity: %lld\n\tmFreeSpaceBytes: %lld\n\tmFreeSpaceObjects: %d\n",
LOGD("\tmMaxCapacity: %lld\n\tmFreeSpaceBytes: %lld\n\tmFreeSpaceObjects: %d\n",
mMaxCapacity, mFreeSpaceBytes, mFreeSpaceObjects);
printf("\tmStorageDescription: %s\n\tmVolumeIdentifier: %s\n",
LOGD("\tmStorageDescription: %s\n\tmVolumeIdentifier: %s\n",
mStorageDescription, mVolumeIdentifier);
}

View File

@@ -23,20 +23,39 @@
namespace android {
typedef int32_t int128_t[4];
typedef uint32_t uint128_t[4];
typedef uint16_t MtpOperationCode;
typedef uint16_t MtpResponseCode;
typedef uint32_t MtpSessionID;
typedef uint32_t MtpStorageID;
typedef uint32_t MtpTransactionID;
typedef uint16_t MtpDeviceProperty;
typedef uint16_t MtpPropertyCode;
typedef uint16_t MtpDataType;
typedef uint16_t MtpObjectFormat;
typedef uint16_t MtpObjectProperty;
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;
typedef union MtpPropertyValue {
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;
char* str;
};
// Special values
#define MTP_PARENT_ROOT 0xFFFFFFFF // parent is root of the storage
#define kInvalidObjectHandle 0xFFFFFFFF
@@ -53,16 +72,18 @@ typedef uint32_t MtpObjectHandle;
class MtpStorage;
class MtpDevice;
class MtpProperty;
typedef Vector<MtpStorage *> MtpStorageList;
typedef Vector<MtpDevice*> MtpDeviceList;
typedef Vector<MtpProperty*> MtpPropertyList;
typedef Vector<uint8_t> UInt8List;
typedef Vector<uint32_t> UInt16List;
typedef Vector<uint16_t> UInt16List;
typedef Vector<uint32_t> UInt32List;
typedef Vector<uint64_t> UInt64List;
typedef Vector<int8_t> Int8List;
typedef Vector<int32_t> Int16List;
typedef Vector<int16_t> Int16List;
typedef Vector<int32_t> Int32List;
typedef Vector<int64_t> Int64List;