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