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