|  | /* | 
|  | * 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 <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <stdio.h> | 
|  |  | 
|  | #include <usbhost/usbhost.h> | 
|  |  | 
|  | 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, | 
|  | 1000); | 
|  | request->actual_length = result; | 
|  | return result; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | }  // namespace android |