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