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 25namespace android { 26 27MtpProperty::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 46MtpProperty::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 99MtpProperty::~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 124void 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 165void 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 206void 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 216void 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 226void 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 275void 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 315void MtpProperty::setFormDateTime() { 316 mFormFlag = kFormDateTime; 317} 318 319void 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 367void 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 410void 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 463void 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 518MtpPropertyValue* 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 528void 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