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