From a6c490b8b2d96ebaab632286029463f932ae3b6b Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Sat, 5 Jun 2010 22:45:01 -0400 Subject: MTP: host support for retrieving device property descriptors Signed-off-by: Mike Lockwood --- media/mtp/Android.mk | 1 + media/mtp/MtpDataPacket.cpp | 21 ++++++ media/mtp/MtpDataPacket.h | 4 ++ media/mtp/MtpDevice.cpp | 52 +++++++++++--- media/mtp/MtpDevice.h | 3 + media/mtp/MtpDeviceInfo.cpp | 7 +- media/mtp/MtpObjectInfo.cpp | 5 +- media/mtp/MtpProperty.cpp | 161 +++++++++++++++++++++++++++++++++++++++++++ media/mtp/MtpProperty.h | 71 +++++++++++++++++++ media/mtp/MtpStorageInfo.cpp | 9 +-- media/mtp/MtpTypes.h | 29 ++++++-- 11 files changed, 339 insertions(+), 24 deletions(-) create mode 100644 media/mtp/MtpProperty.cpp create mode 100644 media/mtp/MtpProperty.h (limited to 'media/mtp') diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk index ec9f17b..9f684e1 100644 --- a/media/mtp/Android.mk +++ b/media/mtp/Android.mk @@ -61,6 +61,7 @@ LOCAL_SRC_FILES:= \ MtpDeviceInfo.cpp \ MtpObjectInfo.cpp \ MtpPacket.cpp \ + MtpProperty.cpp \ MtpRequestPacket.cpp \ MtpResponsePacket.cpp \ MtpStorageInfo.cpp \ diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp index fa086c5..f96284c 100644 --- a/media/mtp/MtpDataPacket.cpp +++ b/media/mtp/MtpDataPacket.cpp @@ -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++) diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h index 03f2b4b..4e743b2 100644 --- a/media/mtp/MtpDataPacket.h +++ b/media/mtp/MtpDataPacket.h @@ -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); diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp index 0282086..5c39628 100644 --- a/media/mtp/MtpDevice.cpp +++ b/media/mtp/MtpDevice.cpp @@ -14,6 +14,9 @@ * limitations under the License. */ +#define LOG_TAG "MtpDevice" +#include "utils/Log.h" + #include #include #include @@ -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; } } diff --git a/media/mtp/MtpDevice.h b/media/mtp/MtpDevice.h index fe4f1bd..226b247 100644 --- a/media/mtp/MtpDevice.h +++ b/media/mtp/MtpDevice.h @@ -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); diff --git a/media/mtp/MtpDeviceInfo.cpp b/media/mtp/MtpDeviceInfo.cpp index 210dfcc..eb25fb3 100644 --- a/media/mtp/MtpDeviceInfo.cpp +++ b/media/mtp/MtpDeviceInfo.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +#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); } diff --git a/media/mtp/MtpObjectInfo.cpp b/media/mtp/MtpObjectInfo.cpp index 8ca2880..a0ee2b6 100644 --- a/media/mtp/MtpObjectInfo.cpp +++ b/media/mtp/MtpObjectInfo.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +#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 diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp new file mode 100644 index 0000000..65ce4d4 --- /dev/null +++ b/media/mtp/MtpProperty.cpp @@ -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 diff --git a/media/mtp/MtpProperty.h b/media/mtp/MtpProperty.h new file mode 100644 index 0000000..6372290 --- /dev/null +++ b/media/mtp/MtpProperty.h @@ -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 diff --git a/media/mtp/MtpStorageInfo.cpp b/media/mtp/MtpStorageInfo.cpp index 7116e2b..5a5306b 100644 --- a/media/mtp/MtpStorageInfo.cpp +++ b/media/mtp/MtpStorageInfo.cpp @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +#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); } diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h index e3389c0..6a33a2b 100644 --- a/media/mtp/MtpTypes.h +++ b/media/mtp/MtpTypes.h @@ -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 MtpStorageList; typedef Vector MtpDeviceList; +typedef Vector MtpPropertyList; typedef Vector UInt8List; -typedef Vector UInt16List; +typedef Vector UInt16List; typedef Vector UInt32List; typedef Vector UInt64List; typedef Vector Int8List; -typedef Vector Int16List; +typedef Vector Int16List; typedef Vector Int32List; typedef Vector Int64List; -- cgit v1.1