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