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