MtpProperty.cpp revision 21ef7d0e70c5ad599bc2602cb484f8cd647055ca
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 "MtpProperty.h"
21#include "MtpStringBuffer.h"
22#include "MtpUtils.h"
23
24namespace android {
25
26MtpProperty::MtpProperty()
27    :   mCode(0),
28        mType(0),
29        mWriteable(false),
30        mDefaultArrayLength(0),
31        mDefaultArrayValues(NULL),
32        mCurrentArrayLength(0),
33        mCurrentArrayValues(NULL),
34        mFormFlag(kFormNone),
35        mEnumLength(0),
36        mEnumValues(NULL)
37{
38    mDefaultValue.str = NULL;
39    mCurrentValue.str = NULL;
40    mMinimumValue.str = NULL;
41    mMaximumValue.str = NULL;
42}
43
44MtpProperty::MtpProperty(MtpPropertyCode propCode,
45                         MtpDataType type,
46                         bool writeable,
47                         int defaultValue)
48    :   mCode(propCode),
49        mType(type),
50        mWriteable(writeable),
51        mDefaultArrayLength(0),
52        mDefaultArrayValues(NULL),
53        mCurrentArrayLength(0),
54        mCurrentArrayValues(NULL),
55        mFormFlag(kFormNone),
56        mEnumLength(0),
57        mEnumValues(NULL)
58{
59    memset(&mDefaultValue, 0, sizeof(mDefaultValue));
60    memset(&mCurrentValue, 0, sizeof(mCurrentValue));
61    memset(&mMinimumValue, 0, sizeof(mMinimumValue));
62    memset(&mMaximumValue, 0, sizeof(mMaximumValue));
63
64    if (defaultValue) {
65        switch (type) {
66            case MTP_TYPE_INT8:
67                mDefaultValue.i8 = defaultValue;
68                break;
69            case MTP_TYPE_UINT8:
70                mDefaultValue.u8 = defaultValue;
71                break;
72            case MTP_TYPE_INT16:
73                mDefaultValue.i16 = defaultValue;
74                break;
75            case MTP_TYPE_UINT16:
76                mDefaultValue.u16 = defaultValue;
77                break;
78            case MTP_TYPE_INT32:
79                mDefaultValue.i32 = defaultValue;
80                break;
81            case MTP_TYPE_UINT32:
82                mDefaultValue.u32 = defaultValue;
83                break;
84            case MTP_TYPE_INT64:
85                mDefaultValue.i64 = defaultValue;
86                break;
87            case MTP_TYPE_UINT64:
88                mDefaultValue.u64 = defaultValue;
89                break;
90            default:
91                LOGE("unknown type %d in MtpProperty::MtpProperty", type);
92        }
93    }
94}
95
96MtpProperty::~MtpProperty() {
97    if (mType == MTP_TYPE_STR) {
98        // free all strings
99        free(mDefaultValue.str);
100        free(mCurrentValue.str);
101        free(mMinimumValue.str);
102        free(mMaximumValue.str);
103        if (mDefaultArrayValues) {
104            for (int i = 0; i < mDefaultArrayLength; i++)
105                free(mDefaultArrayValues[i].str);
106        }
107        if (mCurrentArrayValues) {
108            for (int i = 0; i < mCurrentArrayLength; i++)
109                free(mCurrentArrayValues[i].str);
110        }
111        if (mEnumValues) {
112            for (int i = 0; i < mEnumLength; i++)
113                free(mEnumValues[i].str);
114        }
115    }
116    delete[] mDefaultArrayValues;
117    delete[] mCurrentArrayValues;
118    delete[] mEnumValues;
119}
120
121void MtpProperty::read(MtpDataPacket& packet, bool deviceProp) {
122    MtpStringBuffer string;
123
124    mCode = packet.getUInt16();
125    mType = packet.getUInt16();
126    mWriteable = (packet.getUInt8() == 1);
127    switch (mType) {
128        case MTP_TYPE_AINT8:
129        case MTP_TYPE_AUINT8:
130        case MTP_TYPE_AINT16:
131        case MTP_TYPE_AUINT16:
132        case MTP_TYPE_AINT32:
133        case MTP_TYPE_AUINT32:
134        case MTP_TYPE_AINT64:
135        case MTP_TYPE_AUINT64:
136        case MTP_TYPE_AINT128:
137        case MTP_TYPE_AUINT128:
138            mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
139            mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
140            break;
141        default:
142            readValue(packet, mDefaultValue);
143            if (deviceProp)
144                readValue(packet, mCurrentValue);
145    }
146    mFormFlag = packet.getUInt8();
147
148    if (mFormFlag == kFormRange) {
149            readValue(packet, mMinimumValue);
150            readValue(packet, mMaximumValue);
151            readValue(packet, mStepSize);
152    } else if (mFormFlag == kFormEnum) {
153        mEnumLength = packet.getUInt16();
154        mEnumValues = new MtpPropertyValue[mEnumLength];
155        for (int i = 0; i < mEnumLength; i++)
156            readValue(packet, mEnumValues[i]);
157    }
158}
159
160// FIXME - only works for object properties
161void MtpProperty::write(MtpDataPacket& packet) {
162    packet.putUInt16(mCode);
163    packet.putUInt16(mType);
164    packet.putUInt8(mWriteable ? 1 : 0);
165
166    switch (mType) {
167        case MTP_TYPE_AINT8:
168        case MTP_TYPE_AUINT8:
169        case MTP_TYPE_AINT16:
170        case MTP_TYPE_AUINT16:
171        case MTP_TYPE_AINT32:
172        case MTP_TYPE_AUINT32:
173        case MTP_TYPE_AINT64:
174        case MTP_TYPE_AUINT64:
175        case MTP_TYPE_AINT128:
176        case MTP_TYPE_AUINT128:
177            writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
178            break;
179        default:
180            writeValue(packet, mDefaultValue);
181    }
182    packet.putUInt8(mFormFlag);
183    if (mFormFlag == kFormRange) {
184            writeValue(packet, mMinimumValue);
185            writeValue(packet, mMaximumValue);
186            writeValue(packet, mStepSize);
187    } else if (mFormFlag == kFormEnum) {
188        packet.putUInt16(mEnumLength);
189        for (int i = 0; i < mEnumLength; i++)
190            writeValue(packet, mEnumValues[i]);
191    }
192}
193
194void MtpProperty::print() {
195    LOGD("MtpProperty %04X\n", mCode);
196    LOGD("    type %04X\n", mType);
197    LOGD("    writeable %s\n", (mWriteable ? "true" : "false"));
198}
199
200void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
201    switch (mType) {
202        case MTP_TYPE_INT8:
203            value.i8 = packet.getInt8();
204            break;
205        case MTP_TYPE_UINT8:
206            value.u8 = packet.getUInt8();
207            break;
208        case MTP_TYPE_INT16:
209            value.i16 = packet.getInt16();
210            break;
211        case MTP_TYPE_UINT16:
212            value.u16 = packet.getUInt16();
213            break;
214        case MTP_TYPE_INT32:
215            value.i32 = packet.getInt32();
216            break;
217        case MTP_TYPE_UINT32:
218            value.u32 = packet.getUInt32();
219            break;
220        case MTP_TYPE_INT64:
221            value.i64 = packet.getInt64();
222            break;
223        case MTP_TYPE_UINT64:
224            value.u64 = packet.getUInt64();
225            break;
226        case MTP_TYPE_INT128:
227            packet.getInt128(value.i128);
228            break;
229        case MTP_TYPE_UINT128:
230            packet.getUInt128(value.u128);
231            break;
232        default:
233            LOGE("unknown type %d in MtpProperty::readValue", mType);
234    }
235}
236
237void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
238    switch (mType) {
239        case MTP_TYPE_INT8:
240            packet.putInt8(value.i8);
241            break;
242        case MTP_TYPE_UINT8:
243            packet.putUInt8(value.u8);
244            break;
245        case MTP_TYPE_INT16:
246            packet.putInt16(value.i16);
247            break;
248        case MTP_TYPE_UINT16:
249            packet.putUInt16(value.u16);
250            break;
251        case MTP_TYPE_INT32:
252            packet.putInt32(value.i32);
253            break;
254        case MTP_TYPE_UINT32:
255            packet.putUInt32(value.u32);
256            break;
257        case MTP_TYPE_INT64:
258            packet.putInt64(value.i64);
259            break;
260        case MTP_TYPE_UINT64:
261            packet.putUInt64(value.u64);
262            break;
263        case MTP_TYPE_INT128:
264            packet.putInt128(value.i128);
265            break;
266        case MTP_TYPE_UINT128:
267            packet.putUInt128(value.u128);
268            break;
269        default:
270            LOGE("unknown type %d in MtpProperty::readValue", mType);
271    }
272}
273
274MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
275    length = packet.getUInt32();
276    if (length == 0)
277        return NULL;
278    MtpPropertyValue* result = new MtpPropertyValue[length];
279    for (int i = 0; i < length; i++)
280        readValue(packet, result[i]);
281    return result;
282}
283
284void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
285    packet.putUInt32(length);
286    for (int i = 0; i < length; i++)
287        writeValue(packet, values[i]);
288}
289
290}  // namespace android
291