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