MTP: Implement GetObjectPropDesc
Change-Id: I283651257254fc9cd9d93eab4605c5e33d3db93e Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
@@ -245,7 +245,7 @@ MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
|
||||
MtpResponseCode ret = readResponse();
|
||||
if (ret == MTP_RESPONSE_OK) {
|
||||
MtpProperty* property = new MtpProperty;
|
||||
property->read(mData);
|
||||
property->read(mData, true);
|
||||
return property;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
@@ -41,6 +41,58 @@ MtpProperty::MtpProperty()
|
||||
mMaximumValue.str = NULL;
|
||||
}
|
||||
|
||||
MtpProperty::MtpProperty(MtpPropertyCode propCode,
|
||||
MtpDataType type,
|
||||
bool writeable,
|
||||
int defaultValue)
|
||||
: mCode(propCode),
|
||||
mType(type),
|
||||
mWriteable(writeable),
|
||||
mDefaultArrayLength(0),
|
||||
mDefaultArrayValues(NULL),
|
||||
mCurrentArrayLength(0),
|
||||
mCurrentArrayValues(NULL),
|
||||
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.i8 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_UINT8:
|
||||
mDefaultValue.u8 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_INT16:
|
||||
mDefaultValue.i16 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_UINT16:
|
||||
mDefaultValue.u16 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_INT32:
|
||||
mDefaultValue.i32 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_UINT32:
|
||||
mDefaultValue.u32 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_INT64:
|
||||
mDefaultValue.i64 = defaultValue;
|
||||
break;
|
||||
case MTP_TYPE_UINT64:
|
||||
mDefaultValue.u64 = defaultValue;
|
||||
break;
|
||||
default:
|
||||
LOGE("unknown type %d in MtpProperty::MtpProperty", type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MtpProperty::~MtpProperty() {
|
||||
if (mType == MTP_TYPE_STR) {
|
||||
// free all strings
|
||||
@@ -66,7 +118,7 @@ MtpProperty::~MtpProperty() {
|
||||
delete[] mEnumValues;
|
||||
}
|
||||
|
||||
void MtpProperty::read(MtpDataPacket& packet) {
|
||||
void MtpProperty::read(MtpDataPacket& packet, bool deviceProp) {
|
||||
MtpStringBuffer string;
|
||||
|
||||
mCode = packet.getUInt16();
|
||||
@@ -88,7 +140,8 @@ void MtpProperty::read(MtpDataPacket& packet) {
|
||||
break;
|
||||
default:
|
||||
readValue(packet, mDefaultValue);
|
||||
readValue(packet, mCurrentValue);
|
||||
if (deviceProp)
|
||||
readValue(packet, mCurrentValue);
|
||||
}
|
||||
mFormFlag = packet.getUInt8();
|
||||
|
||||
@@ -104,6 +157,40 @@ void MtpProperty::read(MtpDataPacket& packet) {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - only works for object properties
|
||||
void MtpProperty::write(MtpDataPacket& packet) {
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
writeValue(packet, mDefaultValue);
|
||||
}
|
||||
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::print() {
|
||||
LOGD("MtpProperty %04X\n", mCode);
|
||||
LOGD(" type %04X\n", mType);
|
||||
@@ -147,6 +234,43 @@ void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
|
||||
}
|
||||
}
|
||||
|
||||
void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
|
||||
switch (mType) {
|
||||
case MTP_TYPE_INT8:
|
||||
packet.putInt8(value.i8);
|
||||
break;
|
||||
case MTP_TYPE_UINT8:
|
||||
packet.putUInt8(value.u8);
|
||||
break;
|
||||
case MTP_TYPE_INT16:
|
||||
packet.putInt16(value.i16);
|
||||
break;
|
||||
case MTP_TYPE_UINT16:
|
||||
packet.putUInt16(value.u16);
|
||||
break;
|
||||
case MTP_TYPE_INT32:
|
||||
packet.putInt32(value.i32);
|
||||
break;
|
||||
case MTP_TYPE_UINT32:
|
||||
packet.putUInt32(value.u32);
|
||||
break;
|
||||
case MTP_TYPE_INT64:
|
||||
packet.putInt64(value.i64);
|
||||
break;
|
||||
case MTP_TYPE_UINT64:
|
||||
packet.putUInt64(value.u64);
|
||||
break;
|
||||
case MTP_TYPE_INT128:
|
||||
packet.putInt128(value.i128);
|
||||
break;
|
||||
case MTP_TYPE_UINT128:
|
||||
packet.putUInt128(value.u128);
|
||||
break;
|
||||
default:
|
||||
LOGE("unknown type %d in MtpProperty::readValue", mType);
|
||||
}
|
||||
}
|
||||
|
||||
MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
|
||||
length = packet.getUInt32();
|
||||
if (length == 0)
|
||||
@@ -157,4 +281,10 @@ MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& lengt
|
||||
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]);
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -55,15 +55,24 @@ public:
|
||||
|
||||
public:
|
||||
MtpProperty();
|
||||
MtpProperty(MtpPropertyCode propCode,
|
||||
MtpDataType type,
|
||||
bool writeable = false,
|
||||
int defaultValue = 0);
|
||||
virtual ~MtpProperty();
|
||||
|
||||
void read(MtpDataPacket& packet);
|
||||
inline MtpPropertyCode getPropertyCode() const { return mCode; }
|
||||
|
||||
void read(MtpDataPacket& packet, bool deviceProp);
|
||||
void write(MtpDataPacket& packet);
|
||||
|
||||
void print();
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "MtpServer"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
@@ -27,11 +25,11 @@
|
||||
#include <cutils/properties.h>
|
||||
|
||||
#include "MtpDebug.h"
|
||||
#include "MtpDatabase.h"
|
||||
#include "MtpProperty.h"
|
||||
#include "MtpServer.h"
|
||||
#include "MtpStorage.h"
|
||||
#include "MtpStringBuffer.h"
|
||||
#include "MtpDatabase.h"
|
||||
#include "MtpDebug.h"
|
||||
|
||||
#include "f_mtp.h"
|
||||
|
||||
@@ -126,6 +124,8 @@ MtpServer::MtpServer(int fd, const char* databasePath)
|
||||
{
|
||||
mDatabase = new MtpDatabase();
|
||||
mDatabase->open(databasePath, true);
|
||||
|
||||
initObjectProperties();
|
||||
}
|
||||
|
||||
MtpServer::~MtpServer() {
|
||||
@@ -157,7 +157,7 @@ void MtpServer::scanStorage() {
|
||||
void MtpServer::run() {
|
||||
int fd = mFD;
|
||||
|
||||
LOGD("MtpServer::run fd: %d", fd);
|
||||
LOGV("MtpServer::run fd: %d\n", fd);
|
||||
|
||||
while (1) {
|
||||
int ret = mRequest.read(fd);
|
||||
@@ -222,11 +222,37 @@ void MtpServer::run() {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
LOGV("skipping response");
|
||||
LOGV("skipping response\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MtpProperty* MtpServer::getObjectProperty(MtpPropertyCode propCode) {
|
||||
for (int i = 0; i < mObjectProperties.size(); i++) {
|
||||
MtpProperty* property = mObjectProperties[i];
|
||||
if (property->getPropertyCode() == propCode)
|
||||
return property;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MtpProperty* MtpServer::getDeviceProperty(MtpPropertyCode propCode) {
|
||||
for (int i = 0; i < mDeviceProperties.size(); i++) {
|
||||
MtpProperty* property = mDeviceProperties[i];
|
||||
if (property->getPropertyCode() == propCode)
|
||||
return property;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MtpServer::initObjectProperties() {
|
||||
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT16));
|
||||
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16));
|
||||
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64));
|
||||
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR));
|
||||
mObjectProperties.push(new MtpProperty(MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32));
|
||||
}
|
||||
|
||||
bool MtpServer::handleRequest() {
|
||||
MtpOperationCode operation = mRequest.getOperationCode();
|
||||
MtpResponseCode response;
|
||||
@@ -280,6 +306,8 @@ bool MtpServer::handleRequest() {
|
||||
response = doDeleteObject();
|
||||
break;
|
||||
case MTP_OPERATION_GET_OBJECT_PROP_DESC:
|
||||
response = doGetObjectPropDesc();
|
||||
break;
|
||||
default:
|
||||
response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
|
||||
break;
|
||||
@@ -489,9 +517,6 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
|
||||
time_t modifiedTime;
|
||||
if (!parseDateTime(modified, modifiedTime))
|
||||
modifiedTime = 0;
|
||||
LOGV("SendObjectInfo format: %04X size: %d name: %s, created: %s, modified: %s",
|
||||
format, mSendObjectFileSize, (const char*)name, (const char*)created,
|
||||
(const char*)modified);
|
||||
|
||||
if (path[path.size() - 1] != '/')
|
||||
path += "/";
|
||||
@@ -589,10 +614,14 @@ MtpResponseCode MtpServer::doDeleteObject() {
|
||||
}
|
||||
|
||||
MtpResponseCode MtpServer::doGetObjectPropDesc() {
|
||||
MtpObjectProperty property = mRequest.getParameter(1);
|
||||
MtpObjectProperty propCode = mRequest.getParameter(1);
|
||||
MtpObjectFormat format = mRequest.getParameter(2);
|
||||
MtpProperty* property = getObjectProperty(propCode);
|
||||
if (!property)
|
||||
return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
|
||||
|
||||
return -1;
|
||||
property->write(mData);
|
||||
return MTP_RESPONSE_OK;
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace android {
|
||||
|
||||
class MtpStorage;
|
||||
class MtpDatabase;
|
||||
class MtpProperty;
|
||||
|
||||
class MtpServer {
|
||||
|
||||
@@ -51,6 +52,9 @@ private:
|
||||
|
||||
MtpStorageList mStorages;
|
||||
|
||||
MtpPropertyList mObjectProperties;
|
||||
MtpPropertyList mDeviceProperties;
|
||||
|
||||
// handle for new object, set by SendObjectInfo and used by SendObject
|
||||
MtpObjectHandle mSendObjectHandle;
|
||||
MtpString mSendObjectFilePath;
|
||||
@@ -66,7 +70,12 @@ public:
|
||||
void scanStorage();
|
||||
void run();
|
||||
|
||||
MtpProperty* getObjectProperty(MtpPropertyCode propCode);
|
||||
MtpProperty* getDeviceProperty(MtpPropertyCode propCode);
|
||||
|
||||
private:
|
||||
void initObjectProperties();
|
||||
|
||||
bool handleRequest();
|
||||
|
||||
MtpResponseCode doGetDeviceInfo();
|
||||
|
||||
Reference in New Issue
Block a user