123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574 |
- /*
- * 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 <inttypes.h>
- #include <cutils/compiler.h>
- #include <iomanip>
- #include <sstream>
- #include <string>
- #include "MtpDataPacket.h"
- #include "MtpDebug.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),
- 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:
- ALOGE("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 (uint32_t i = 0; i < mDefaultArrayLength; i++)
- free(mDefaultArrayValues[i].str);
- }
- if (mCurrentArrayValues) {
- for (uint32_t i = 0; i < mCurrentArrayLength; i++)
- free(mCurrentArrayValues[i].str);
- }
- if (mEnumValues) {
- for (uint16_t i = 0; i < mEnumLength; i++)
- free(mEnumValues[i].str);
- }
- }
- delete[] mDefaultArrayValues;
- delete[] mCurrentArrayValues;
- delete[] mEnumValues;
- }
- bool MtpProperty::read(MtpDataPacket& packet) {
- uint8_t temp8;
- if (!packet.getUInt16(mCode)) return false;
- bool deviceProp = isDeviceProperty();
- if (!packet.getUInt16(mType)) return false;
- if (!packet.getUInt8(temp8)) return false;
- mWriteable = (temp8 == 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 (!mDefaultArrayValues) return false;
- if (deviceProp) {
- mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
- if (!mCurrentArrayValues) return false;
- }
- break;
- default:
- if (!readValue(packet, mDefaultValue)) return false;
- if (deviceProp) {
- if (!readValue(packet, mCurrentValue)) return false;
- }
- }
- if (!deviceProp) {
- if (!packet.getUInt32(mGroupCode)) return false;
- }
- if (!packet.getUInt8(mFormFlag)) return false;
- if (mFormFlag == kFormRange) {
- if (!readValue(packet, mMinimumValue)) return false;
- if (!readValue(packet, mMaximumValue)) return false;
- if (!readValue(packet, mStepSize)) return false;
- } else if (mFormFlag == kFormEnum) {
- if (!packet.getUInt16(mEnumLength)) return false;
- mEnumValues = new MtpPropertyValue[mEnumLength];
- for (int i = 0; i < mEnumLength; i++) {
- if (!readValue(packet, mEnumValues[i])) return false;
- }
- }
- return true;
- }
- 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);
- }
- if (!deviceProp)
- packet.putUInt32(mGroupCode);
- 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::setCurrentValue(MtpDataPacket& packet) {
- free(mCurrentValue.str);
- mCurrentValue.str = NULL;
- readValue(packet, mCurrentValue);
- }
- 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:
- ALOGE("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:
- ALOGE("unsupported type for MtpProperty::setEnum");
- break;
- }
- }
- }
- void MtpProperty::setFormDateTime() {
- mFormFlag = kFormDateTime;
- }
- void MtpProperty::print() {
- std::string buffer;
- bool deviceProp = isDeviceProperty();
- if (deviceProp)
- ALOGI(" %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
- else
- ALOGI(" %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
- ALOGI(" type %04X", mType);
- ALOGI(" writeable %s", (mWriteable ? "true" : "false"));
- buffer = " default value: ";
- print(mDefaultValue, buffer);
- ALOGI("%s", buffer.c_str());
- if (deviceProp) {
- buffer = " current value: ";
- print(mCurrentValue, buffer);
- ALOGI("%s", buffer.c_str());
- }
- switch (mFormFlag) {
- case kFormNone:
- break;
- case kFormRange:
- buffer = " Range (";
- print(mMinimumValue, buffer);
- buffer += ", ";
- print(mMaximumValue, buffer);
- buffer += ", ";
- print(mStepSize, buffer);
- buffer += ")";
- ALOGI("%s", buffer.c_str());
- break;
- case kFormEnum:
- buffer = " Enum { ";
- for (int i = 0; i < mEnumLength; i++) {
- print(mEnumValues[i], buffer);
- buffer += " ";
- }
- buffer += "}";
- ALOGI("%s", buffer.c_str());
- break;
- case kFormDateTime:
- ALOGI(" DateTime\n");
- break;
- default:
- ALOGI(" form %d\n", mFormFlag);
- break;
- }
- }
- void MtpProperty::print(MtpPropertyValue& value, std::string& buffer) {
- std::ostringstream s;
- switch (mType) {
- case MTP_TYPE_INT8:
- buffer += std::to_string(value.u.i8);
- break;
- case MTP_TYPE_UINT8:
- buffer += std::to_string(value.u.u8);
- break;
- case MTP_TYPE_INT16:
- buffer += std::to_string(value.u.i16);
- break;
- case MTP_TYPE_UINT16:
- buffer += std::to_string(value.u.u16);
- break;
- case MTP_TYPE_INT32:
- buffer += std::to_string(value.u.i32);
- break;
- case MTP_TYPE_UINT32:
- buffer += std::to_string(value.u.u32);
- break;
- case MTP_TYPE_INT64:
- buffer += std::to_string(value.u.i64);
- break;
- case MTP_TYPE_UINT64:
- buffer += std::to_string(value.u.u64);
- break;
- case MTP_TYPE_INT128:
- for (auto i : value.u.i128) {
- s << std::hex << std::setfill('0') << std::uppercase << i;
- }
- buffer += s.str();
- break;
- case MTP_TYPE_UINT128:
- for (auto i : value.u.u128) {
- s << std::hex << std::setfill('0') << std::uppercase << i;
- }
- buffer += s.str();
- break;
- case MTP_TYPE_STR:
- buffer += value.str;
- break;
- default:
- ALOGE("unsupported type for MtpProperty::print\n");
- break;
- }
- }
- bool MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
- MtpStringBuffer stringBuffer;
- switch (mType) {
- case MTP_TYPE_INT8:
- case MTP_TYPE_AINT8:
- if (!packet.getInt8(value.u.i8)) return false;
- break;
- case MTP_TYPE_UINT8:
- case MTP_TYPE_AUINT8:
- if (!packet.getUInt8(value.u.u8)) return false;
- break;
- case MTP_TYPE_INT16:
- case MTP_TYPE_AINT16:
- if (!packet.getInt16(value.u.i16)) return false;
- break;
- case MTP_TYPE_UINT16:
- case MTP_TYPE_AUINT16:
- if (!packet.getUInt16(value.u.u16)) return false;
- break;
- case MTP_TYPE_INT32:
- case MTP_TYPE_AINT32:
- if (!packet.getInt32(value.u.i32)) return false;
- break;
- case MTP_TYPE_UINT32:
- case MTP_TYPE_AUINT32:
- if (!packet.getUInt32(value.u.u32)) return false;
- break;
- case MTP_TYPE_INT64:
- case MTP_TYPE_AINT64:
- if (!packet.getInt64(value.u.i64)) return false;
- break;
- case MTP_TYPE_UINT64:
- case MTP_TYPE_AUINT64:
- if (!packet.getUInt64(value.u.u64)) return false;
- break;
- case MTP_TYPE_INT128:
- case MTP_TYPE_AINT128:
- if (!packet.getInt128(value.u.i128)) return false;
- break;
- case MTP_TYPE_UINT128:
- case MTP_TYPE_AUINT128:
- if (!packet.getUInt128(value.u.u128)) return false;
- break;
- case MTP_TYPE_STR:
- if (!packet.getString(stringBuffer)) return false;
- value.str = strdup(stringBuffer);
- break;
- default:
- ALOGE("unknown type %04X in MtpProperty::readValue", mType);
- return false;
- }
- return true;
- }
- 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:
- ALOGE("unknown type %04X in MtpProperty::writeValue", mType);
- }
- }
- MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, uint32_t& length) {
- if (!packet.getUInt32(length)) return NULL;
- // Fail if resulting array is over 2GB. This is because the maximum array
- // size may be less than SIZE_MAX on some platforms.
- if ( CC_UNLIKELY(
- length == 0 ||
- length >= INT32_MAX / sizeof(MtpPropertyValue)) ) {
- length = 0;
- return NULL;
- }
- MtpPropertyValue* result = new MtpPropertyValue[length];
- for (uint32_t i = 0; i < length; i++)
- if (!readValue(packet, result[i])) {
- delete [] result;
- return NULL;
- }
- return result;
- }
- void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, uint32_t length) {
- packet.putUInt32(length);
- for (uint32_t i = 0; i < length; i++)
- writeValue(packet, values[i]);
- }
- } // namespace android
|