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
31namespace android {
32
33MtpProperty::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
52MtpProperty::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
105MtpProperty::~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
130bool 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
182void 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
223void 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
233void 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
243void MtpProperty::setCurrentValue(MtpDataPacket& packet) {
244    free(mCurrentValue.str);
245    mCurrentValue.str = NULL;
246    readValue(packet, mCurrentValue);
247}
248
249void 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
298void 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
338void MtpProperty::setFormDateTime() {
339     mFormFlag = kFormDateTime;
340}
341
342void 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
390void 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
438bool 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
493void 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
548MtpPropertyValue* 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
568void 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