/*
 * 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.
 *
 * Copyright (C) 2014 TeamWin - bigbiff and Dees_Troy mtp database conversion to C++
 */

#include "MtpDebug.h"
#include "MtpPacket.h"
#include "mtp.h"

#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>

#include <usbhost/usbhost.h>


MtpPacket::MtpPacket(int bufferSize)
	:   mBuffer(NULL),
		mBufferSize(bufferSize),
		mAllocationIncrement(bufferSize),
		mPacketSize(0)
{
	mBuffer = (uint8_t *)malloc(bufferSize);
	if (!mBuffer) {
		MTPE("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(int length) {
	if (length > mBufferSize) {
		int newLength = length + mAllocationIncrement;
		mBuffer = (uint8_t *)realloc(mBuffer, newLength);
		if (!mBuffer) {
			MTPE("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++) {
		sprintf(bufptr, "%02X ", mBuffer[i]);
		bufptr += strlen(bufptr);
		if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
			MTPD("%s", buffer);
			bufptr = buffer;
		}
	}
	if (bufptr != buffer) {
		// print last line
		MTPD("%s", buffer);
	}
	MTPD("\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) {
		MTPE("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) {
		MTPE("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,
							0);
	request->actual_length = result;
	return result;
}
#endif

