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