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