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