MtpProperty.cpp revision f43c641bf3f8bcb5748f4ae504d434896edc94f5
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 %04X 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
123    mCode = packet.getUInt16();
124    mType = packet.getUInt16();
125    mWriteable = (packet.getUInt8() == 1);
126    switch (mType) {
127        case MTP_TYPE_AINT8:
128        case MTP_TYPE_AUINT8:
129        case MTP_TYPE_AINT16:
130        case MTP_TYPE_AUINT16:
131        case MTP_TYPE_AINT32:
132        case MTP_TYPE_AUINT32:
133        case MTP_TYPE_AINT64:
134        case MTP_TYPE_AUINT64:
135        case MTP_TYPE_AINT128:
136        case MTP_TYPE_AUINT128:
137            mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
138            mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
139            break;
140        default:
141            readValue(packet, mDefaultValue);
142            if (deviceProp)
143                readValue(packet, mCurrentValue);
144    }
145    mFormFlag = packet.getUInt8();
146
147    if (mFormFlag == kFormRange) {
148            readValue(packet, mMinimumValue);
149            readValue(packet, mMaximumValue);
150            readValue(packet, mStepSize);
151    } else if (mFormFlag == kFormEnum) {
152        mEnumLength = packet.getUInt16();
153        mEnumValues = new MtpPropertyValue[mEnumLength];
154        for (int i = 0; i < mEnumLength; i++)
155            readValue(packet, mEnumValues[i]);
156    }
157}
158
159// FIXME - only works for object properties
160void MtpProperty::write(MtpDataPacket& packet) {
161    packet.putUInt16(mCode);
162    packet.putUInt16(mType);
163    packet.putUInt8(mWriteable ? 1 : 0);
164
165    switch (mType) {
166        case MTP_TYPE_AINT8:
167        case MTP_TYPE_AUINT8:
168        case MTP_TYPE_AINT16:
169        case MTP_TYPE_AUINT16:
170        case MTP_TYPE_AINT32:
171        case MTP_TYPE_AUINT32:
172        case MTP_TYPE_AINT64:
173        case MTP_TYPE_AUINT64:
174        case MTP_TYPE_AINT128:
175        case MTP_TYPE_AUINT128:
176            writeArrayValues(packet, mDefaultArrayValues, mDefaultArrayLength);
177            break;
178        default:
179            writeValue(packet, mDefaultValue);
180    }
181    packet.putUInt8(mFormFlag);
182    if (mFormFlag == kFormRange) {
183            writeValue(packet, mMinimumValue);
184            writeValue(packet, mMaximumValue);
185            writeValue(packet, mStepSize);
186    } else if (mFormFlag == kFormEnum) {
187        packet.putUInt16(mEnumLength);
188        for (int i = 0; i < mEnumLength; i++)
189            writeValue(packet, mEnumValues[i]);
190    }
191}
192
193void MtpProperty::print() {
194    LOGV("MtpProperty %04X\n", mCode);
195    LOGV("    type %04X\n", mType);
196    LOGV("    writeable %s\n", (mWriteable ? "true" : "false"));
197}
198
199void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
200    MtpStringBuffer stringBuffer;
201
202    switch (mType) {
203        case MTP_TYPE_INT8:
204        case MTP_TYPE_AINT8:
205            value.i8 = packet.getInt8();
206            break;
207        case MTP_TYPE_UINT8:
208        case MTP_TYPE_AUINT8:
209            value.u8 = packet.getUInt8();
210            break;
211        case MTP_TYPE_INT16:
212        case MTP_TYPE_AINT16:
213            value.i16 = packet.getInt16();
214            break;
215        case MTP_TYPE_UINT16:
216        case MTP_TYPE_AUINT16:
217            value.u16 = packet.getUInt16();
218            break;
219        case MTP_TYPE_INT32:
220        case MTP_TYPE_AINT32:
221            value.i32 = packet.getInt32();
222            break;
223        case MTP_TYPE_UINT32:
224        case MTP_TYPE_AUINT32:
225            value.u32 = packet.getUInt32();
226            break;
227        case MTP_TYPE_INT64:
228        case MTP_TYPE_AINT64:
229            value.i64 = packet.getInt64();
230            break;
231        case MTP_TYPE_UINT64:
232        case MTP_TYPE_AUINT64:
233            value.u64 = packet.getUInt64();
234            break;
235        case MTP_TYPE_INT128:
236        case MTP_TYPE_AINT128:
237            packet.getInt128(value.i128);
238            break;
239        case MTP_TYPE_UINT128:
240        case MTP_TYPE_AUINT128:
241            packet.getUInt128(value.u128);
242            break;
243        case MTP_TYPE_STR:
244            packet.getString(stringBuffer);
245            value.str = strdup(stringBuffer);
246            break;
247        default:
248            LOGE("unknown type %04X in MtpProperty::readValue", mType);
249    }
250}
251
252void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
253    MtpStringBuffer stringBuffer;
254
255    switch (mType) {
256        case MTP_TYPE_INT8:
257        case MTP_TYPE_AINT8:
258            packet.putInt8(value.i8);
259            break;
260        case MTP_TYPE_UINT8:
261        case MTP_TYPE_AUINT8:
262            packet.putUInt8(value.u8);
263            break;
264        case MTP_TYPE_INT16:
265        case MTP_TYPE_AINT16:
266            packet.putInt16(value.i16);
267            break;
268        case MTP_TYPE_UINT16:
269        case MTP_TYPE_AUINT16:
270            packet.putUInt16(value.u16);
271            break;
272        case MTP_TYPE_INT32:
273        case MTP_TYPE_AINT32:
274            packet.putInt32(value.i32);
275            break;
276        case MTP_TYPE_UINT32:
277        case MTP_TYPE_AUINT32:
278            packet.putUInt32(value.u32);
279            break;
280        case MTP_TYPE_INT64:
281        case MTP_TYPE_AINT64:
282            packet.putInt64(value.i64);
283            break;
284        case MTP_TYPE_UINT64:
285        case MTP_TYPE_AUINT64:
286            packet.putUInt64(value.u64);
287            break;
288        case MTP_TYPE_INT128:
289        case MTP_TYPE_AINT128:
290            packet.putInt128(value.i128);
291            break;
292        case MTP_TYPE_UINT128:
293        case MTP_TYPE_AUINT128:
294            packet.putUInt128(value.u128);
295            break;
296        case MTP_TYPE_STR:
297            if (value.str)
298                packet.putString(value.str);
299            else
300                packet.putEmptyString();
301            break;
302        default:
303            LOGE("unknown type %04X in MtpProperty::writeValue", mType);
304    }
305}
306
307MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {
308    length = packet.getUInt32();
309    if (length == 0)
310        return NULL;
311    MtpPropertyValue* result = new MtpPropertyValue[length];
312    for (int i = 0; i < length; i++)
313        readValue(packet, result[i]);
314    return result;
315}
316
317void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {
318    packet.putUInt32(length);
319    for (int i = 0; i < length; i++)
320        writeValue(packet, values[i]);
321}
322
323}  // namespace android
324