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 "MtpPacket" 18 19 #include "MtpDebug.h" 20 #include "MtpPacket.h" 21 #include "mtp.h" 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <stdio.h> 26 27 #include <usbhost/usbhost.h> 28 29 namespace android { 30 31 MtpPacket::MtpPacket(int bufferSize) 32 : mBuffer(NULL), 33 mBufferSize(bufferSize), 34 mAllocationIncrement(bufferSize), 35 mPacketSize(0) 36 { 37 mBuffer = (uint8_t *)malloc(bufferSize); 38 if (!mBuffer) { 39 ALOGE("out of memory!"); 40 abort(); 41 } 42 } 43 44 MtpPacket::~MtpPacket() { 45 if (mBuffer) 46 free(mBuffer); 47 } 48 49 void MtpPacket::reset() { 50 allocate(MTP_CONTAINER_HEADER_SIZE); 51 mPacketSize = MTP_CONTAINER_HEADER_SIZE; 52 memset(mBuffer, 0, mBufferSize); 53 } 54 55 void MtpPacket::allocate(int length) { 56 if (length > mBufferSize) { 57 int newLength = length + mAllocationIncrement; 58 mBuffer = (uint8_t *)realloc(mBuffer, newLength); 59 if (!mBuffer) { 60 ALOGE("out of memory!"); 61 abort(); 62 } 63 mBufferSize = newLength; 64 } 65 } 66 67 void MtpPacket::dump() { 68 #define DUMP_BYTES_PER_ROW 16 69 char buffer[500]; 70 char* bufptr = buffer; 71 72 for (int i = 0; i < mPacketSize; i++) { 73 sprintf(bufptr, "%02X ", mBuffer[i]); 74 bufptr += strlen(bufptr); 75 if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) { 76 ALOGV("%s", buffer); 77 bufptr = buffer; 78 } 79 } 80 if (bufptr != buffer) { 81 // print last line 82 ALOGV("%s", buffer); 83 } 84 ALOGV("\n"); 85 } 86 87 void MtpPacket::copyFrom(const MtpPacket& src) { 88 int length = src.mPacketSize; 89 allocate(length); 90 mPacketSize = length; 91 memcpy(mBuffer, src.mBuffer, length); 92 } 93 94 uint16_t MtpPacket::getUInt16(int offset) const { 95 return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; 96 } 97 98 uint32_t MtpPacket::getUInt32(int offset) const { 99 return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | 100 ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; 101 } 102 103 void MtpPacket::putUInt16(int offset, uint16_t value) { 104 mBuffer[offset++] = (uint8_t)(value & 0xFF); 105 mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); 106 } 107 108 void MtpPacket::putUInt32(int offset, uint32_t value) { 109 mBuffer[offset++] = (uint8_t)(value & 0xFF); 110 mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); 111 mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); 112 mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); 113 } 114 115 uint16_t MtpPacket::getContainerCode() const { 116 return getUInt16(MTP_CONTAINER_CODE_OFFSET); 117 } 118 119 void MtpPacket::setContainerCode(uint16_t code) { 120 putUInt16(MTP_CONTAINER_CODE_OFFSET, code); 121 } 122 123 uint16_t MtpPacket::getContainerType() const { 124 return getUInt16(MTP_CONTAINER_TYPE_OFFSET); 125 } 126 127 MtpTransactionID MtpPacket::getTransactionID() const { 128 return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET); 129 } 130 131 void MtpPacket::setTransactionID(MtpTransactionID id) { 132 putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id); 133 } 134 135 uint32_t MtpPacket::getParameter(int index) const { 136 if (index < 1 || index > 5) { 137 ALOGE("index %d out of range in MtpPacket::getParameter", index); 138 return 0; 139 } 140 return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t)); 141 } 142 143 void MtpPacket::setParameter(int index, uint32_t value) { 144 if (index < 1 || index > 5) { 145 ALOGE("index %d out of range in MtpPacket::setParameter", index); 146 return; 147 } 148 int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t); 149 if (mPacketSize < offset + sizeof(uint32_t)) 150 mPacketSize = offset + sizeof(uint32_t); 151 putUInt32(offset, value); 152 } 153 154 #ifdef MTP_HOST 155 int MtpPacket::transfer(struct usb_request* request) { 156 int result = usb_device_bulk_transfer(request->dev, 157 request->endpoint, 158 request->buffer, 159 request->buffer_length, 160 0); 161 request->actual_length = result; 162 return result; 163 } 164 #endif 165 166 } // namespace android 167