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