/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "MtpPacket" #include "MtpDebug.h" #include "MtpPacket.h" #include "mtp.h" #include #include #include #include namespace android { MtpPacket::MtpPacket(int bufferSize) : mBuffer(NULL), mBufferSize(bufferSize), mAllocationIncrement(bufferSize), mPacketSize(0) { mBuffer = (uint8_t *)malloc(bufferSize); if (!mBuffer) { ALOGE("out of memory!"); abort(); } } MtpPacket::~MtpPacket() { if (mBuffer) free(mBuffer); } void MtpPacket::reset() { allocate(MTP_CONTAINER_HEADER_SIZE); mPacketSize = MTP_CONTAINER_HEADER_SIZE; memset(mBuffer, 0, mBufferSize); } void MtpPacket::allocate(size_t length) { if (length > mBufferSize) { int newLength = length + mAllocationIncrement; mBuffer = (uint8_t *)realloc(mBuffer, newLength); if (!mBuffer) { ALOGE("out of memory!"); abort(); } mBufferSize = newLength; } } void MtpPacket::dump() { #define DUMP_BYTES_PER_ROW 16 char buffer[500]; char* bufptr = buffer; for (size_t i = 0; i < mPacketSize; i++) { bufptr += snprintf(bufptr, sizeof(buffer) - (bufptr - buffer), "%02X ", mBuffer[i]); if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) { ALOGV("%s", buffer); bufptr = buffer; } } if (bufptr != buffer) { // print last line ALOGV("%s", buffer); } ALOGV("\n"); } void MtpPacket::copyFrom(const MtpPacket& src) { int length = src.mPacketSize; allocate(length); mPacketSize = length; memcpy(mBuffer, src.mBuffer, length); } uint16_t MtpPacket::getUInt16(int offset) const { return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; } uint32_t MtpPacket::getUInt32(int offset) const { return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; } void MtpPacket::putUInt16(int offset, uint16_t value) { mBuffer[offset++] = (uint8_t)(value & 0xFF); mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); } void MtpPacket::putUInt32(int offset, uint32_t value) { mBuffer[offset++] = (uint8_t)(value & 0xFF); mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF); mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF); } uint16_t MtpPacket::getContainerCode() const { return getUInt16(MTP_CONTAINER_CODE_OFFSET); } void MtpPacket::setContainerCode(uint16_t code) { putUInt16(MTP_CONTAINER_CODE_OFFSET, code); } uint16_t MtpPacket::getContainerType() const { return getUInt16(MTP_CONTAINER_TYPE_OFFSET); } MtpTransactionID MtpPacket::getTransactionID() const { return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET); } void MtpPacket::setTransactionID(MtpTransactionID id) { putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id); } uint32_t MtpPacket::getParameter(int index) const { if (index < 1 || index > 5) { ALOGE("index %d out of range in MtpPacket::getParameter", index); return 0; } return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t)); } void MtpPacket::setParameter(int index, uint32_t value) { if (index < 1 || index > 5) { ALOGE("index %d out of range in MtpPacket::setParameter", index); return; } int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t); if (mPacketSize < offset + sizeof(uint32_t)) mPacketSize = offset + sizeof(uint32_t); putUInt32(offset, value); } #ifdef MTP_HOST int MtpPacket::transfer(struct usb_request* request) { int result = usb_device_bulk_transfer(request->dev, request->endpoint, request->buffer, request->buffer_length, 5000); request->actual_length = result; return result; } #endif } // namespace android