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