Home | History | Annotate | Download | only in mtp
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "MtpProperty"
     18 
     19 #include "MtpDataPacket.h"
     20 #include "MtpDebug.h"
     21 #include "MtpProperty.h"
     22 #include "MtpStringBuffer.h"
     23 #include "MtpUtils.h"
     24 
     25 namespace android {
     26 
     27 MtpProperty::MtpProperty()
     28     :   mCode(0),
     29         mType(0),
     30         mWriteable(false),
     31         mDefaultArrayLength(0),
     32         mDefaultArrayValues(NULL),
     33         mCurrentArrayLength(0),
     34         mCurrentArrayValues(NULL),
     35         mGroupCode(0),
     36         mFormFlag(kFormNone),
     37         mEnumLength(0),
     38         mEnumValues(NULL)
     39 {
     40     memset(&mDefaultValue, 0, sizeof(mDefaultValue));
     41     memset(&mCurrentValue, 0, sizeof(mCurrentValue));
     42     memset(&mMinimumValue, 0, sizeof(mMinimumValue));
     43     memset(&mMaximumValue, 0, sizeof(mMaximumValue));
     44 }
     45 
     46 MtpProperty::MtpProperty(MtpPropertyCode propCode,
     47                          MtpDataType type,
     48                          bool writeable,
     49                          int defaultValue)
     50     :   mCode(propCode),
     51         mType(type),
     52         mWriteable(writeable),
     53         mDefaultArrayLength(0),
     54         mDefaultArrayValues(NULL),
     55         mCurrentArrayLength(0),
     56         mCurrentArrayValues(NULL),
     57         mGroupCode(0),
     58         mFormFlag(kFormNone),
     59         mEnumLength(0),
     60         mEnumValues(NULL)
     61 {
     62     memset(&mDefaultValue, 0, sizeof(mDefaultValue));
     63     memset(&mCurrentValue, 0, sizeof(mCurrentValue));
     64     memset(&mMinimumValue, 0, sizeof(mMinimumValue));
     65     memset(&mMaximumValue, 0, sizeof(mMaximumValue));
     66 
     67     if (defaultValue) {
     68         switch (type) {
     69             case MTP_TYPE_INT8:
     70                 mDefaultValue.u.i8 = defaultValue;
     71                 break;
     72             case MTP_TYPE_UINT8:
     73                 mDefaultValue.u.u8 = defaultValue;
     74                 break;
     75             case MTP_TYPE_INT16:
     76                 mDefaultValue.u.i16 = defaultValue;
     77                 break;
     78             case MTP_TYPE_UINT16:
     79                 mDefaultValue.u.u16 = defaultValue;
     80                 break;
     81             case MTP_TYPE_INT32:
     82                 mDefaultValue.u.i32 = defaultValue;
     83                 break;
     84             case MTP_TYPE_UINT32:
     85                 mDefaultValue.u.u32 = defaultValue;
     86                 break;
     87             case MTP_TYPE_INT64:
     88                 mDefaultValue.u.i64 = defaultValue;
     89                 break;
     90             case MTP_TYPE_UINT64:
     91                 mDefaultValue.u.u64 = defaultValue;
     92                 break;
     93             default:
     94                 ALOGE("unknown type %04X in MtpProperty::MtpProperty", type);
     95         }
     96     }
     97 }
     98 
     99 MtpProperty::~MtpProperty() {
    100     if (mType == MTP_TYPE_STR) {
    101         // free all strings
    102         free(mDefaultValue.str);
    103         free(mCurrentValue.str);
    104         free(mMinimumValue.str);
    105         free(mMaximumValue.str);
    106         if (mDefaultArrayValues) {
    107             for (int i = 0; i < mDefaultArrayLength; i++)
    108                 free(mDefaultArrayValues[i].str);
    109         }
    110         if (mCurrentArrayValues) {
    111             for (int i = 0; i < mCurrentArrayLength; i++)
    112                 free(mCurrentArrayValues[i].str);
    113         }
    114         if (mEnumValues) {
    115             for (int i = 0; i < mEnumLength; i++)
    116                 free(mEnumValues[i].str);
    117         }
    118     }
    119     delete[] mDefaultArrayValues;
    120     delete[] mCurrentArrayValues;
    121     delete[] mEnumValues;
    122 }
    123 
    124 void MtpProperty::read(MtpDataPacket& packet) {
    125     mCode = packet.getUInt16();
    126     bool deviceProp = isDeviceProperty();
    127     mType = packet.getUInt16();
    128     mWriteable = (packet.getUInt8() == 1);
    129     switch (mType) {
    130         case MTP_TYPE_AINT8:
    131         case MTP_TYPE_AUINT8:
    132         case MTP_TYPE_AINT16:
    133         case MTP_TYPE_AUINT16:
    134         case MTP_TYPE_AINT32:
    135         case MTP_TYPE_AUINT32:
    136         case MTP_TYPE_AINT64:
    137         case MTP_TYPE_AUINT64:
    138         case MTP_TYPE_AINT128:
    139         case MTP_TYPE_AUINT128:
    140             mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
    141             if (deviceProp)
    142                 mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
    143             break;
    144         default:
    145             readValue(packet, mDefaultValue);
    146             if (deviceProp)
    147                 readValue(packet, mCurrentValue);
    148     }
    149     if (!deviceProp)
    150         mGroupCode = packet.getUInt32();
    151     mFormFlag = packet.getUInt8();
    152 
    153     if (mFormFlag == kFormRange) {
    154             readValue(packet, mMinimumValue);
    155             readValue(packet, mMaximumValue);
    156             readValue(packet, mStepSize);
    157     } else if (mFormFlag == kFormEnum) {
    158         mEnumLength = packet.getUInt16();
    159         mEnumValues = new MtpPropertyValue[mEnumLength];
    160         for (int i = 0; i < mEnumLength; i++)
    161             readValue(packet, mEnumValues[i]);
    162     }
    163 }
    164 
    165 void MtpProperty::write(MtpDataPacket& packet) {
    166     bool deviceProp = isDeviceProperty();
    167 
    168     packet.putUInt16(mCode);
    169     packet.putUInt16(mType);
    170     packet.putUInt8(mWriteable ? 1 : 0);
    171 
    172     switch (mType) {
    173         case MTP_TYPE_AINT8:
    174         case MTP_TYPE_AUINT8:
    175         case MTP_TYPE_AINT16:
    176         case MTP_TYPE_AUINT16:
    177         case MTP_TYPE_AINT32:
    178         case MTP_TYPE_AUINT32:
    179         case MTP_TYPE_AINT64:
    180         case MTP_TYPE_AUINT64:
    181         case MTP_TYPE_AINT128:
    182         case MTP_TYPE_AUINT128:
    183             writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
    184             if (deviceProp)
    185                 writeArrayValues(packet, mCurrentArrayValues, mCurrentArrayLength);
    186             break;
    187         default:
    188             writeValue(packet, mDefaultValue);
    189             if (deviceProp)
    190                 writeValue(packet, mCurrentValue);
    191     }
    192     packet.putUInt32(mGroupCode);
    193     if (!deviceProp)
    194         packet.putUInt8(mFormFlag);
    195     if (mFormFlag == kFormRange) {
    196             writeValue(packet, mMinimumValue);
    197             writeValue(packet, mMaximumValue);
    198             writeValue(packet, mStepSize);
    199     } else if (mFormFlag == kFormEnum) {
    200         packet.putUInt16(mEnumLength);
    201         for (int i = 0; i < mEnumLength; i++)
    202             writeValue(packet, mEnumValues[i]);
    203     }
    204 }
    205 
    206 void MtpProperty::setDefaultValue(const uint16_t* string) {
    207     free(mDefaultValue.str);
    208     if (string) {
    209         MtpStringBuffer buffer(string);
    210         mDefaultValue.str = strdup(buffer);
    211     }
    212     else
    213         mDefaultValue.str = NULL;
    214 }
    215 
    216 void MtpProperty::setCurrentValue(const uint16_t* string) {
    217     free(mCurrentValue.str);
    218     if (string) {
    219         MtpStringBuffer buffer(string);
    220         mCurrentValue.str = strdup(buffer);
    221     }
    222     else
    223         mCurrentValue.str = NULL;
    224 }
    225 
    226 void MtpProperty::setFormRange(int min, int max, int step) {
    227     mFormFlag = kFormRange;
    228     switch (mType) {
    229         case MTP_TYPE_INT8:
    230             mMinimumValue.u.i8 = min;
    231             mMaximumValue.u.i8 = max;
    232             mStepSize.u.i8 = step;
    233             break;
    234         case MTP_TYPE_UINT8:
    235             mMinimumValue.u.u8 = min;
    236             mMaximumValue.u.u8 = max;
    237             mStepSize.u.u8 = step;
    238             break;
    239         case MTP_TYPE_INT16:
    240             mMinimumValue.u.i16 = min;
    241             mMaximumValue.u.i16 = max;
    242             mStepSize.u.i16 = step;
    243             break;
    244         case MTP_TYPE_UINT16:
    245             mMinimumValue.u.u16 = min;
    246             mMaximumValue.u.u16 = max;
    247             mStepSize.u.u16 = step;
    248             break;
    249         case MTP_TYPE_INT32:
    250             mMinimumValue.u.i32 = min;
    251             mMaximumValue.u.i32 = max;
    252             mStepSize.u.i32 = step;
    253             break;
    254         case MTP_TYPE_UINT32:
    255             mMinimumValue.u.u32 = min;
    256             mMaximumValue.u.u32 = max;
    257             mStepSize.u.u32 = step;
    258             break;
    259         case MTP_TYPE_INT64:
    260             mMinimumValue.u.i64 = min;
    261             mMaximumValue.u.i64 = max;
    262             mStepSize.u.i64 = step;
    263             break;
    264         case MTP_TYPE_UINT64:
    265             mMinimumValue.u.u64 = min;
    266             mMaximumValue.u.u64 = max;
    267             mStepSize.u.u64 = step;
    268             break;
    269         default:
    270             ALOGE("unsupported type for MtpProperty::setRange");
    271             break;
    272     }
    273 }
    274 
    275 void MtpProperty::setFormEnum(const int* values, int count) {
    276      mFormFlag = kFormEnum;
    277      delete[] mEnumValues;
    278      mEnumValues = new MtpPropertyValue[count];
    279      mEnumLength = count;
    280 
    281     for (int i = 0; i < count; i++) {
    282         int value = *values++;
    283             switch (mType) {
    284                 case MTP_TYPE_INT8:
    285                     mEnumValues[i].u.i8 = value;
    286                     break;
    287                 case MTP_TYPE_UINT8:
    288                     mEnumValues[i].u.u8 = value;
    289                     break;
    290                 case MTP_TYPE_INT16:
    291                     mEnumValues[i].u.i16 = value;
    292                     break;
    293                 case MTP_TYPE_UINT16:
    294                     mEnumValues[i].u.u16 = value;
    295                     break;
    296                 case MTP_TYPE_INT32:
    297                     mEnumValues[i].u.i32 = value;
    298                     break;
    299                 case MTP_TYPE_UINT32:
    300                     mEnumValues[i].u.u32 = value;
    301                     break;
    302                 case MTP_TYPE_INT64:
    303                     mEnumValues[i].u.i64 = value;
    304                     break;
    305                 case MTP_TYPE_UINT64:
    306                     mEnumValues[i].u.u64 = value;
    307                     break;
    308                 default:
    309                     ALOGE("unsupported type for MtpProperty::setEnum");
    310                     break;
    311         }
    312     }
    313 }
    314 
    315 void MtpProperty::setFormDateTime() {
    316      mFormFlag = kFormDateTime;
    317 }
    318 
    319 void MtpProperty::print() {
    320     MtpString buffer;
    321     bool deviceProp = isDeviceProperty();
    322     if (deviceProp)
    323         ALOGI("    %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
    324     else
    325         ALOGI("    %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
    326     ALOGI("    type %04X", mType);
    327     ALOGI("    writeable %s", (mWriteable ? "true" : "false"));
    328     buffer = "    default value: ";
    329     print(mDefaultValue, buffer);
    330     ALOGI("%s", (const char *)buffer);
    331     if (deviceProp) {
    332         buffer = "    current value: ";
    333         print(mCurrentValue, buffer);
    334         ALOGI("%s", (const char *)buffer);
    335     }
    336     switch (mFormFlag) {
    337         case kFormNone:
    338             break;
    339         case kFormRange:
    340             buffer = "    Range (";
    341             print(mMinimumValue, buffer);
    342             buffer += ", ";
    343             print(mMaximumValue, buffer);
    344             buffer += ", ";
    345             print(mStepSize, buffer);
    346             buffer += ")";
    347             ALOGI("%s", (const char *)buffer);
    348             break;
    349         case kFormEnum:
    350             buffer = "    Enum { ";
    351             for (int i = 0; i < mEnumLength; i++) {
    352                 print(mEnumValues[i], buffer);
    353                 buffer += " ";
    354             }
    355             buffer += "}";
    356             ALOGI("%s", (const char *)buffer);
    357             break;
    358         case kFormDateTime:
    359             ALOGI("    DateTime\n");
    360             break;
    361         default:
    362             ALOGI("    form %d\n", mFormFlag);
    363             break;
    364     }
    365 }
    366 
    367 void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
    368     switch (mType) {
    369         case MTP_TYPE_INT8:
    370             buffer.appendFormat("%d", value.u.i8);
    371             break;
    372         case MTP_TYPE_UINT8:
    373             buffer.appendFormat("%d", value.u.u8);
    374             break;
    375         case MTP_TYPE_INT16:
    376             buffer.appendFormat("%d", value.u.i16);
    377             break;
    378         case MTP_TYPE_UINT16:
    379             buffer.appendFormat("%d", value.u.u16);
    380             break;
    381         case MTP_TYPE_INT32:
    382             buffer.appendFormat("%d", value.u.i32);
    383             break;
    384         case MTP_TYPE_UINT32:
    385             buffer.appendFormat("%d", value.u.u32);
    386             break;
    387         case MTP_TYPE_INT64:
    388             buffer.appendFormat("%lld", value.u.i64);
    389             break;
    390         case MTP_TYPE_UINT64:
    391             buffer.appendFormat("%lld", value.u.u64);
    392             break;
    393         case MTP_TYPE_INT128:
    394             buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
    395                     value.u.i128[2], value.u.i128[3]);
    396             break;
    397         case MTP_TYPE_UINT128:
    398             buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
    399                     value.u.u128[2], value.u.u128[3]);
    400             break;
    401         case MTP_TYPE_STR:
    402             buffer.appendFormat("%s", value.str);
    403             break;
    404         default:
    405             ALOGE("unsupported type for MtpProperty::print\n");
    406             break;
    407     }
    408 }
    409 
    410 void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
    411     MtpStringBuffer stringBuffer;
    412 
    413     switch (mType) {
    414         case MTP_TYPE_INT8:
    415         case MTP_TYPE_AINT8:
    416             value.u.i8 = packet.getInt8();
    417             break;
    418         case MTP_TYPE_UINT8:
    419         case MTP_TYPE_AUINT8:
    420             value.u.u8 = packet.getUInt8();
    421             break;
    422         case MTP_TYPE_INT16:
    423         case MTP_TYPE_AINT16:
    424             value.u.i16 = packet.getInt16();
    425             break;
    426         case MTP_TYPE_UINT16:
    427         case MTP_TYPE_AUINT16:
    428             value.u.u16 = packet.getUInt16();
    429             break;
    430         case MTP_TYPE_INT32:
    431         case MTP_TYPE_AINT32:
    432             value.u.i32 = packet.getInt32();
    433             break;
    434         case MTP_TYPE_UINT32:
    435         case MTP_TYPE_AUINT32:
    436             value.u.u32 = packet.getUInt32();
    437             break;
    438         case MTP_TYPE_INT64:
    439         case MTP_TYPE_AINT64:
    440             value.u.i64 = packet.getInt64();
    441             break;
    442         case MTP_TYPE_UINT64:
    443         case MTP_TYPE_AUINT64:
    444             value.u.u64 = packet.getUInt64();
    445             break;
    446         case MTP_TYPE_INT128:
    447         case MTP_TYPE_AINT128:
    448             packet.getInt128(value.u.i128);
    449             break;
    450         case MTP_TYPE_UINT128:
    451         case MTP_TYPE_AUINT128:
    452             packet.getUInt128(value.u.u128);
    453             break;
    454         case MTP_TYPE_STR:
    455             packet.getString(stringBuffer);
    456             value.str = strdup(stringBuffer);
    457             break;
    458         default:
    459             ALOGE("unknown type %04X in MtpProperty::readValue", mType);
    460     }
    461 }
    462 
    463 void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
    464     MtpStringBuffer stringBuffer;
    465 
    466     switch (mType) {
    467         case MTP_TYPE_INT8:
    468         case MTP_TYPE_AINT8:
    469             packet.putInt8(value.u.i8);
    470             break;
    471         case MTP_TYPE_UINT8:
    472         case MTP_TYPE_AUINT8:
    473             packet.putUInt8(value.u.u8);
    474             break;
    475         case MTP_TYPE_INT16:
    476         case MTP_TYPE_AINT16:
    477             packet.putInt16(value.u.i16);
    478             break;
    479         case MTP_TYPE_UINT16:
    480         case MTP_TYPE_AUINT16:
    481             packet.putUInt16(value.u.u16);
    482             break;
    483         case MTP_TYPE_INT32:
    484         case MTP_TYPE_AINT32:
    485             packet.putInt32(value.u.i32);
    486             break;
    487         case MTP_TYPE_UINT32:
    488         case MTP_TYPE_AUINT32:
    489             packet.putUInt32(value.u.u32);
    490             break;
    491         case MTP_TYPE_INT64:
    492         case MTP_TYPE_AINT64:
    493             packet.putInt64(value.u.i64);
    494             break;
    495         case MTP_TYPE_UINT64:
    496         case MTP_TYPE_AUINT64:
    497             packet.putUInt64(value.u.u64);
    498             break;
    499         case MTP_TYPE_INT128:
    500         case MTP_TYPE_AINT128:
    501             packet.putInt128(value.u.i128);
    502             break;
    503         case MTP_TYPE_UINT128:
    504         case MTP_TYPE_AUINT128:
    505             packet.putUInt128(value.u.u128);
    506             break;
    507         case MTP_TYPE_STR:
    508             if (value.str)
    509                 packet.putString(value.str);
    510             else
    511                 packet.putEmptyString();
    512             break;
    513         default:
    514             ALOGE("unknown type %04X in MtpProperty::writeValue", mType);
    515     }
    516 }
    517 
    518 MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
    519     length = packet.getUInt32();
    520     if (length == 0)
    521         return NULL;
    522     MtpPropertyValue* result = new MtpPropertyValue[length];
    523     for (int i = 0; i < length; i++)
    524         readValue(packet, result[i]);
    525     return result;
    526 }
    527 
    528 void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
    529     packet.putUInt32(length);
    530     for (int i = 0; i < length; i++)
    531         writeValue(packet, values[i]);
    532 }
    533 
    534 }  // namespace android
    535