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 31namespace android { 32 33MtpProperty::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 52MtpProperty::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 105MtpProperty::~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 130bool 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 182void 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 223void 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 233void 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 243void MtpProperty::setCurrentValue(MtpDataPacket& packet) { 244 free(mCurrentValue.str); 245 mCurrentValue.str = NULL; 246 readValue(packet, mCurrentValue); 247} 248 249void 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 298void 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 338void MtpProperty::setFormDateTime() { 339 mFormFlag = kFormDateTime; 340} 341 342void 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 390void 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 438bool 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 493void 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 548MtpPropertyValue* 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 568void 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