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 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 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 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 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 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 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 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 239 void MtpProperty::setCurrentValue(MtpDataPacket& packet) { 240 free(mCurrentValue.str); 241 mCurrentValue.str = NULL; 242 readValue(packet, mCurrentValue); 243 } 244 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 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 334 void MtpProperty::setFormDateTime() { 335 mFormFlag = kFormDateTime; 336 } 337 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 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 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 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 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 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