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 
setCurrentValue(MtpDataPacket & packet)239 void MtpProperty::setCurrentValue(MtpDataPacket& packet) {
240     free(mCurrentValue.str);
241     mCurrentValue.str = NULL;
242     readValue(packet, mCurrentValue);
243 }
244 
setFormRange(int min,int max,int step)245 void MtpProperty::setFormRange(int min, int max, int step) {
246     mFormFlag = kFormRange;
247     switch (mType) {
248         case MTP_TYPE_INT8:
249             mMinimumValue.u.i8 = min;
250             mMaximumValue.u.i8 = max;
251             mStepSize.u.i8 = step;
252             break;
253         case MTP_TYPE_UINT8:
254             mMinimumValue.u.u8 = min;
255             mMaximumValue.u.u8 = max;
256             mStepSize.u.u8 = step;
257             break;
258         case MTP_TYPE_INT16:
259             mMinimumValue.u.i16 = min;
260             mMaximumValue.u.i16 = max;
261             mStepSize.u.i16 = step;
262             break;
263         case MTP_TYPE_UINT16:
264             mMinimumValue.u.u16 = min;
265             mMaximumValue.u.u16 = max;
266             mStepSize.u.u16 = step;
267             break;
268         case MTP_TYPE_INT32:
269             mMinimumValue.u.i32 = min;
270             mMaximumValue.u.i32 = max;
271             mStepSize.u.i32 = step;
272             break;
273         case MTP_TYPE_UINT32:
274             mMinimumValue.u.u32 = min;
275             mMaximumValue.u.u32 = max;
276             mStepSize.u.u32 = step;
277             break;
278         case MTP_TYPE_INT64:
279             mMinimumValue.u.i64 = min;
280             mMaximumValue.u.i64 = max;
281             mStepSize.u.i64 = step;
282             break;
283         case MTP_TYPE_UINT64:
284             mMinimumValue.u.u64 = min;
285             mMaximumValue.u.u64 = max;
286             mStepSize.u.u64 = step;
287             break;
288         default:
289             ALOGE("unsupported type for MtpProperty::setRange");
290             break;
291     }
292 }
293 
setFormEnum(const int * values,int count)294 void MtpProperty::setFormEnum(const int* values, int count) {
295      mFormFlag = kFormEnum;
296      delete[] mEnumValues;
297      mEnumValues = new MtpPropertyValue[count];
298      mEnumLength = count;
299 
300     for (int i = 0; i < count; i++) {
301         int value = *values++;
302             switch (mType) {
303                 case MTP_TYPE_INT8:
304                     mEnumValues[i].u.i8 = value;
305                     break;
306                 case MTP_TYPE_UINT8:
307                     mEnumValues[i].u.u8 = value;
308                     break;
309                 case MTP_TYPE_INT16:
310                     mEnumValues[i].u.i16 = value;
311                     break;
312                 case MTP_TYPE_UINT16:
313                     mEnumValues[i].u.u16 = value;
314                     break;
315                 case MTP_TYPE_INT32:
316                     mEnumValues[i].u.i32 = value;
317                     break;
318                 case MTP_TYPE_UINT32:
319                     mEnumValues[i].u.u32 = value;
320                     break;
321                 case MTP_TYPE_INT64:
322                     mEnumValues[i].u.i64 = value;
323                     break;
324                 case MTP_TYPE_UINT64:
325                     mEnumValues[i].u.u64 = value;
326                     break;
327                 default:
328                     ALOGE("unsupported type for MtpProperty::setEnum");
329                     break;
330         }
331     }
332 }
333 
setFormDateTime()334 void MtpProperty::setFormDateTime() {
335      mFormFlag = kFormDateTime;
336 }
337 
print()338 void MtpProperty::print() {
339     MtpString buffer;
340     bool deviceProp = isDeviceProperty();
341     if (deviceProp)
342         ALOGI("    %s (%04X)", MtpDebug::getDevicePropCodeName(mCode), mCode);
343     else
344         ALOGI("    %s (%04X)", MtpDebug::getObjectPropCodeName(mCode), mCode);
345     ALOGI("    type %04X", mType);
346     ALOGI("    writeable %s", (mWriteable ? "true" : "false"));
347     buffer = "    default value: ";
348     print(mDefaultValue, buffer);
349     ALOGI("%s", (const char *)buffer);
350     if (deviceProp) {
351         buffer = "    current value: ";
352         print(mCurrentValue, buffer);
353         ALOGI("%s", (const char *)buffer);
354     }
355     switch (mFormFlag) {
356         case kFormNone:
357             break;
358         case kFormRange:
359             buffer = "    Range (";
360             print(mMinimumValue, buffer);
361             buffer += ", ";
362             print(mMaximumValue, buffer);
363             buffer += ", ";
364             print(mStepSize, buffer);
365             buffer += ")";
366             ALOGI("%s", (const char *)buffer);
367             break;
368         case kFormEnum:
369             buffer = "    Enum { ";
370             for (int i = 0; i < mEnumLength; i++) {
371                 print(mEnumValues[i], buffer);
372                 buffer += " ";
373             }
374             buffer += "}";
375             ALOGI("%s", (const char *)buffer);
376             break;
377         case kFormDateTime:
378             ALOGI("    DateTime\n");
379             break;
380         default:
381             ALOGI("    form %d\n", mFormFlag);
382             break;
383     }
384 }
385 
print(MtpPropertyValue & value,MtpString & buffer)386 void MtpProperty::print(MtpPropertyValue& value, MtpString& buffer) {
387     switch (mType) {
388         case MTP_TYPE_INT8:
389             buffer.appendFormat("%d", value.u.i8);
390             break;
391         case MTP_TYPE_UINT8:
392             buffer.appendFormat("%d", value.u.u8);
393             break;
394         case MTP_TYPE_INT16:
395             buffer.appendFormat("%d", value.u.i16);
396             break;
397         case MTP_TYPE_UINT16:
398             buffer.appendFormat("%d", value.u.u16);
399             break;
400         case MTP_TYPE_INT32:
401             buffer.appendFormat("%d", value.u.i32);
402             break;
403         case MTP_TYPE_UINT32:
404             buffer.appendFormat("%d", value.u.u32);
405             break;
406         case MTP_TYPE_INT64:
407             buffer.appendFormat("%" PRId64, value.u.i64);
408             break;
409         case MTP_TYPE_UINT64:
410             buffer.appendFormat("%" PRIu64, value.u.u64);
411             break;
412         case MTP_TYPE_INT128:
413             buffer.appendFormat("%08X%08X%08X%08X", value.u.i128[0], value.u.i128[1],
414                     value.u.i128[2], value.u.i128[3]);
415             break;
416         case MTP_TYPE_UINT128:
417             buffer.appendFormat("%08X%08X%08X%08X", value.u.u128[0], value.u.u128[1],
418                     value.u.u128[2], value.u.u128[3]);
419             break;
420         case MTP_TYPE_STR:
421             buffer.appendFormat("%s", value.str);
422             break;
423         default:
424             ALOGE("unsupported type for MtpProperty::print\n");
425             break;
426     }
427 }
428 
readValue(MtpDataPacket & packet,MtpPropertyValue & value)429 bool MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
430     MtpStringBuffer stringBuffer;
431 
432     switch (mType) {
433         case MTP_TYPE_INT8:
434         case MTP_TYPE_AINT8:
435             if (!packet.getInt8(value.u.i8)) return false;
436             break;
437         case MTP_TYPE_UINT8:
438         case MTP_TYPE_AUINT8:
439             if (!packet.getUInt8(value.u.u8)) return false;
440             break;
441         case MTP_TYPE_INT16:
442         case MTP_TYPE_AINT16:
443             if (!packet.getInt16(value.u.i16)) return false;
444             break;
445         case MTP_TYPE_UINT16:
446         case MTP_TYPE_AUINT16:
447             if (!packet.getUInt16(value.u.u16)) return false;
448             break;
449         case MTP_TYPE_INT32:
450         case MTP_TYPE_AINT32:
451             if (!packet.getInt32(value.u.i32)) return false;
452             break;
453         case MTP_TYPE_UINT32:
454         case MTP_TYPE_AUINT32:
455             if (!packet.getUInt32(value.u.u32)) return false;
456             break;
457         case MTP_TYPE_INT64:
458         case MTP_TYPE_AINT64:
459             if (!packet.getInt64(value.u.i64)) return false;
460             break;
461         case MTP_TYPE_UINT64:
462         case MTP_TYPE_AUINT64:
463             if (!packet.getUInt64(value.u.u64)) return false;
464             break;
465         case MTP_TYPE_INT128:
466         case MTP_TYPE_AINT128:
467             if (!packet.getInt128(value.u.i128)) return false;
468             break;
469         case MTP_TYPE_UINT128:
470         case MTP_TYPE_AUINT128:
471             if (!packet.getUInt128(value.u.u128)) return false;
472             break;
473         case MTP_TYPE_STR:
474             if (!packet.getString(stringBuffer)) return false;
475             value.str = strdup(stringBuffer);
476             break;
477         default:
478             ALOGE("unknown type %04X in MtpProperty::readValue", mType);
479             return false;
480     }
481     return true;
482 }
483 
writeValue(MtpDataPacket & packet,MtpPropertyValue & value)484 void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
485     MtpStringBuffer stringBuffer;
486 
487     switch (mType) {
488         case MTP_TYPE_INT8:
489         case MTP_TYPE_AINT8:
490             packet.putInt8(value.u.i8);
491             break;
492         case MTP_TYPE_UINT8:
493         case MTP_TYPE_AUINT8:
494             packet.putUInt8(value.u.u8);
495             break;
496         case MTP_TYPE_INT16:
497         case MTP_TYPE_AINT16:
498             packet.putInt16(value.u.i16);
499             break;
500         case MTP_TYPE_UINT16:
501         case MTP_TYPE_AUINT16:
502             packet.putUInt16(value.u.u16);
503             break;
504         case MTP_TYPE_INT32:
505         case MTP_TYPE_AINT32:
506             packet.putInt32(value.u.i32);
507             break;
508         case MTP_TYPE_UINT32:
509         case MTP_TYPE_AUINT32:
510             packet.putUInt32(value.u.u32);
511             break;
512         case MTP_TYPE_INT64:
513         case MTP_TYPE_AINT64:
514             packet.putInt64(value.u.i64);
515             break;
516         case MTP_TYPE_UINT64:
517         case MTP_TYPE_AUINT64:
518             packet.putUInt64(value.u.u64);
519             break;
520         case MTP_TYPE_INT128:
521         case MTP_TYPE_AINT128:
522             packet.putInt128(value.u.i128);
523             break;
524         case MTP_TYPE_UINT128:
525         case MTP_TYPE_AUINT128:
526             packet.putUInt128(value.u.u128);
527             break;
528         case MTP_TYPE_STR:
529             if (value.str)
530                 packet.putString(value.str);
531             else
532                 packet.putEmptyString();
533             break;
534         default:
535             ALOGE("unknown type %04X in MtpProperty::writeValue", mType);
536     }
537 }
538 
readArrayValues(MtpDataPacket & packet,uint32_t & length)539 MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, uint32_t& length) {
540     if (!packet.getUInt32(length)) return NULL;
541 
542     // Fail if resulting array is over 2GB.  This is because the maximum array
543     // size may be less than SIZE_MAX on some platforms.
544     if ( CC_UNLIKELY(
545             length == 0 ||
546             length >= INT32_MAX / sizeof(MtpPropertyValue)) ) {
547         length = 0;
548         return NULL;
549     }
550     MtpPropertyValue* result = new MtpPropertyValue[length];
551     for (uint32_t i = 0; i < length; i++)
552         if (!readValue(packet, result[i])) {
553             delete [] result;
554             return NULL;
555         }
556     return result;
557 }
558 
writeArrayValues(MtpDataPacket & packet,MtpPropertyValue * values,uint32_t length)559 void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, uint32_t length) {
560     packet.putUInt32(length);
561     for (uint32_t i = 0; i < length; i++)
562         writeValue(packet, values[i]);
563 }
564 
565 }  // namespace android
566