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