MtpDataPacket.cpp revision 3e072b354d1e1e3ee62d58492f0739139df8aff1
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#include <stdio.h> 18#include <sys/types.h> 19#include <fcntl.h> 20 21#include "MtpDataPacket.h" 22#include "MtpStringBuffer.h" 23 24namespace android { 25 26MtpDataPacket::MtpDataPacket() 27 : MtpPacket(512), 28 mOffset(MTP_CONTAINER_HEADER_SIZE) 29{ 30} 31 32MtpDataPacket::~MtpDataPacket() { 33} 34 35void MtpDataPacket::reset() { 36 MtpPacket::reset(); 37 mOffset = MTP_CONTAINER_HEADER_SIZE; 38} 39 40void MtpDataPacket::setOperationCode(MtpOperationCode code) { 41 MtpPacket::putUInt16(MTP_CONTAINER_CODE_OFFSET, code); 42} 43 44void MtpDataPacket::setTransactionID(MtpTransactionID id) { 45 MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id); 46} 47 48uint16_t MtpDataPacket::getUInt16() { 49 int offset = mOffset; 50 uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8); 51 mOffset += 2; 52 return result; 53} 54 55uint32_t MtpDataPacket::getUInt32() { 56 int offset = mOffset; 57 uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) | 58 ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24); 59 mOffset += 4; 60 return result; 61} 62 63uint64_t MtpDataPacket::getUInt64() { 64 int offset = mOffset; 65 uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) | 66 ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) | 67 ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) | 68 ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56); 69 mOffset += 8; 70 return result; 71} 72 73void MtpDataPacket::getUInt128(uint128_t& value) { 74 value[0] = getUInt32(); 75 value[1] = getUInt32(); 76 value[2] = getUInt32(); 77 value[3] = getUInt32(); 78} 79 80void MtpDataPacket::getString(MtpStringBuffer& string) 81{ 82 string.readFromPacket(this); 83} 84 85Int8List* MtpDataPacket::getAInt8() { 86 Int8List* result = new Int8List; 87 int count = getUInt32(); 88 for (int i = 0; i < count; i++) 89 result->push(getInt8()); 90 return result; 91} 92 93UInt8List* MtpDataPacket::getAUInt8() { 94 UInt8List* result = new UInt8List; 95 int count = getUInt32(); 96 for (int i = 0; i < count; i++) 97 result->push(getUInt8()); 98 return result; 99} 100 101Int16List* MtpDataPacket::getAInt16() { 102 Int16List* result = new Int16List; 103 int count = getUInt32(); 104 for (int i = 0; i < count; i++) 105 result->push(getInt16()); 106 return result; 107} 108 109UInt16List* MtpDataPacket::getAUInt16() { 110 UInt16List* result = new UInt16List; 111 int count = getUInt32(); 112 for (int i = 0; i < count; i++) 113 result->push(getUInt16()); 114 return result; 115} 116 117Int32List* MtpDataPacket::getAInt32() { 118 Int32List* result = new Int32List; 119 int count = getUInt32(); 120 for (int i = 0; i < count; i++) 121 result->push(getInt32()); 122 return result; 123} 124 125UInt32List* MtpDataPacket::getAUInt32() { 126 UInt32List* result = new UInt32List; 127 int count = getUInt32(); 128 for (int i = 0; i < count; i++) 129 result->push(getUInt32()); 130 return result; 131} 132 133Int64List* MtpDataPacket::getAInt64() { 134 Int64List* result = new Int64List; 135 int count = getUInt32(); 136 for (int i = 0; i < count; i++) 137 result->push(getInt64()); 138 return result; 139} 140 141UInt64List* MtpDataPacket::getAUInt64() { 142 UInt64List* result = new UInt64List; 143 int count = getUInt32(); 144 for (int i = 0; i < count; i++) 145 result->push(getUInt64()); 146 return result; 147} 148 149void MtpDataPacket::putInt8(int8_t value) { 150 allocate(mOffset + 1); 151 mBuffer[mOffset++] = (uint8_t)value; 152 if (mPacketSize < mOffset) 153 mPacketSize = mOffset; 154} 155 156void MtpDataPacket::putUInt8(uint8_t value) { 157 allocate(mOffset + 1); 158 mBuffer[mOffset++] = (uint8_t)value; 159 if (mPacketSize < mOffset) 160 mPacketSize = mOffset; 161} 162 163void MtpDataPacket::putInt16(int16_t value) { 164 allocate(mOffset + 2); 165 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 166 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 167 if (mPacketSize < mOffset) 168 mPacketSize = mOffset; 169} 170 171void MtpDataPacket::putUInt16(uint16_t value) { 172 allocate(mOffset + 2); 173 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 174 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 175 if (mPacketSize < mOffset) 176 mPacketSize = mOffset; 177} 178 179void MtpDataPacket::putInt32(int32_t value) { 180 allocate(mOffset + 4); 181 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 182 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 183 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 184 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 185 if (mPacketSize < mOffset) 186 mPacketSize = mOffset; 187} 188 189void MtpDataPacket::putUInt32(uint32_t value) { 190 allocate(mOffset + 4); 191 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 192 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 193 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 194 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 195 if (mPacketSize < mOffset) 196 mPacketSize = mOffset; 197} 198 199void MtpDataPacket::putInt64(int64_t value) { 200 allocate(mOffset + 8); 201 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 202 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 203 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 204 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 205 mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF); 206 mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF); 207 mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF); 208 mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF); 209 if (mPacketSize < mOffset) 210 mPacketSize = mOffset; 211} 212 213void MtpDataPacket::putUInt64(uint64_t value) { 214 allocate(mOffset + 8); 215 mBuffer[mOffset++] = (uint8_t)(value & 0xFF); 216 mBuffer[mOffset++] = (uint8_t)((value >> 8) & 0xFF); 217 mBuffer[mOffset++] = (uint8_t)((value >> 16) & 0xFF); 218 mBuffer[mOffset++] = (uint8_t)((value >> 24) & 0xFF); 219 mBuffer[mOffset++] = (uint8_t)((value >> 32) & 0xFF); 220 mBuffer[mOffset++] = (uint8_t)((value >> 40) & 0xFF); 221 mBuffer[mOffset++] = (uint8_t)((value >> 48) & 0xFF); 222 mBuffer[mOffset++] = (uint8_t)((value >> 56) & 0xFF); 223 if (mPacketSize < mOffset) 224 mPacketSize = mOffset; 225} 226 227void MtpDataPacket::putInt128(const int128_t& value) { 228 putInt32(value[0]); 229 putInt32(value[1]); 230 putInt32(value[2]); 231 putInt32(value[3]); 232} 233 234void MtpDataPacket::putUInt128(const uint128_t& value) { 235 putUInt32(value[0]); 236 putUInt32(value[1]); 237 putUInt32(value[2]); 238 putUInt32(value[3]); 239} 240 241void MtpDataPacket::putAInt8(const int8_t* values, int count) { 242 putUInt32(count); 243 for (int i = 0; i < count; i++) 244 putInt8(*values++); 245} 246 247void MtpDataPacket::putAUInt8(const uint8_t* values, int count) { 248 putUInt32(count); 249 for (int i = 0; i < count; i++) 250 putUInt8(*values++); 251} 252 253void MtpDataPacket::putAInt16(const int16_t* values, int count) { 254 putUInt32(count); 255 for (int i = 0; i < count; i++) 256 putInt16(*values++); 257} 258 259void MtpDataPacket::putAUInt16(const uint16_t* values, int count) { 260 putUInt32(count); 261 for (int i = 0; i < count; i++) 262 putUInt16(*values++); 263} 264 265void MtpDataPacket::putAInt32(const int32_t* values, int count) { 266 putUInt32(count); 267 for (int i = 0; i < count; i++) 268 putInt32(*values++); 269} 270 271void MtpDataPacket::putAUInt32(const uint32_t* values, int count) { 272 putUInt32(count); 273 for (int i = 0; i < count; i++) 274 putUInt32(*values++); 275} 276 277void MtpDataPacket::putAUInt32(const UInt32List* list) { 278 if (!list) { 279 putEmptyArray(); 280 } else { 281 size_t size = list->size(); 282 putUInt32(size); 283 for (size_t i = 0; i < size; i++) 284 putUInt32((*list)[i]); 285 } 286} 287 288void MtpDataPacket::putAInt64(const int64_t* values, int count) { 289 putUInt32(count); 290 for (int i = 0; i < count; i++) 291 putInt64(*values++); 292} 293 294void MtpDataPacket::putAUInt64(const uint64_t* values, int count) { 295 putUInt32(count); 296 for (int i = 0; i < count; i++) 297 putUInt64(*values++); 298} 299 300void MtpDataPacket::putString(const MtpStringBuffer& string) 301{ 302 string.writeToPacket(this); 303} 304 305void MtpDataPacket::putString(const char* s) 306{ 307 MtpStringBuffer string(s); 308 string.writeToPacket(this); 309} 310 311#ifdef MTP_DEVICE 312int MtpDataPacket::read(int fd) { 313 // first read the header 314 int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); 315printf("MtpDataPacket::read 1 returned %d\n", ret); 316 if (ret != MTP_CONTAINER_HEADER_SIZE) 317 return -1; 318 // then the following data 319 int total = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); 320 int remaining = total - MTP_CONTAINER_HEADER_SIZE; 321printf("total: %d, remaining: %d\n", total, remaining); 322 ret = ::read(fd, &mBuffer[0] + MTP_CONTAINER_HEADER_SIZE, remaining); 323printf("MtpDataPacket::read 2 returned %d\n", ret); 324 if (ret != remaining) 325 return -1; 326 327 mPacketSize = total; 328 mOffset = MTP_CONTAINER_HEADER_SIZE; 329 return total; 330} 331 332int MtpDataPacket::readDataHeader(int fd) { 333 int ret = ::read(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); 334 if (ret > 0) 335 mPacketSize = ret; 336 else 337 mPacketSize = 0; 338 return ret; 339} 340 341int MtpDataPacket::write(int fd) { 342 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); 343 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); 344 345 // send header separately from data 346 int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); 347 if (ret == MTP_CONTAINER_HEADER_SIZE) 348 ret = ::write(fd, mBuffer + MTP_CONTAINER_HEADER_SIZE, 349 mPacketSize - MTP_CONTAINER_HEADER_SIZE); 350 return (ret < 0 ? ret : 0); 351} 352 353int MtpDataPacket::writeDataHeader(int fd, uint32_t length) { 354 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length); 355 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); 356 int ret = ::write(fd, mBuffer, MTP_CONTAINER_HEADER_SIZE); 357 return (ret < 0 ? ret : 0); 358} 359#endif // MTP_DEVICE 360 361#ifdef MTP_HOST 362int MtpDataPacket::read(struct usb_endpoint *ep) { 363 // first read the header 364 int length = transfer(ep, mBuffer, mBufferSize); 365 if (length > MTP_CONTAINER_HEADER_SIZE) { 366 // look at the length field to see if the data spans multiple packets 367 uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); 368 while (totalLength > length) { 369 allocate(length + mAllocationIncrement); 370 int ret = transfer(ep, mBuffer + length, mAllocationIncrement); 371 if (ret >= 0) 372 length += ret; 373 else { 374 length = ret; 375 break; 376 } 377 } 378 } 379 if (length >= 0) 380 mPacketSize = length; 381 return length; 382} 383 384int MtpDataPacket::write(struct usb_endpoint *ep) { 385 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, mPacketSize); 386 MtpPacket::putUInt16(MTP_CONTAINER_TYPE_OFFSET, MTP_CONTAINER_TYPE_DATA); 387 388 // send header separately from data 389 int ret = transfer(ep, mBuffer, MTP_CONTAINER_HEADER_SIZE); 390 if (ret == MTP_CONTAINER_HEADER_SIZE) 391 ret = transfer(ep, mBuffer + MTP_CONTAINER_HEADER_SIZE, 392 mPacketSize - MTP_CONTAINER_HEADER_SIZE); 393 return (ret < 0 ? ret : 0); 394} 395 396#endif // MTP_HOST 397 398void* MtpDataPacket::getData(int& outLength) const { 399 int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE; 400 if (length > 0) { 401 void* result = malloc(length); 402 if (result) { 403 memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length); 404 outLength = length; 405 return result; 406 } 407 } 408 outLength = 0; 409 return NULL; 410} 411 412} // namespace android 413