| /* |
| * 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 { |
| if ((unsigned long)(offset+2) <= mBufferSize) { |
| return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset]; |
| } |
| else { |
| ALOGE("offset for buffer read is greater than buffer size!"); |
| return 0; |
| } |
| } |
| |
| uint32_t MtpPacket::getUInt32(int offset) const { |
| if ((unsigned long)(offset+4) <= mBufferSize) { |
| return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) | |
| ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset]; |
| } |
| else { |
| ALOGE("offset for buffer read is greater than buffer size!"); |
| return 0; |
| } |
| } |
| |
| void MtpPacket::putUInt16(int offset, uint16_t value) { |
| if ((unsigned long)(offset+2) <= mBufferSize) { |
| mBuffer[offset++] = (uint8_t)(value & 0xFF); |
| mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF); |
| } |
| else { |
| ALOGE("offset for buffer write is greater than buffer size!"); |
| } |
| } |
| |
| void MtpPacket::putUInt32(int offset, uint32_t value) { |
| if ((unsigned long)(offset+4) <= mBufferSize) { |
| 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); |
| } |
| else { |
| ALOGE("offset for buffer write is greater than buffer size!"); |
| } |
| } |
| |
| 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); |
| allocate(mPacketSize); |
| } |
| putUInt32(offset, value); |
| } |
| |
| #ifdef MTP_HOST |
| int MtpPacket::transfer(struct usb_request* request) { |
| if (request->dev == NULL) { |
| return -1; |
| } |
| 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 |