116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood/*
216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Copyright (C) 2010 The Android Open Source Project
316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *
416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * you may not use this file except in compliance with the License.
616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * You may obtain a copy of the License at
716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *
816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood *
1016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * Unless required by applicable law or agreed to in writing, software
1116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
1216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * See the License for the specific language governing permissions and
1416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood * limitations under the License.
1516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood */
1616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
17b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#define LOG_TAG "MtpPacket"
18b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood
19b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpDebug.h"
20b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "MtpPacket.h"
21b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#include "mtp.h"
22b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood
2316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h>
2416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdlib.h>
2516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <stdio.h>
2616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
2716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#include <usbhost/usbhost.h>
2816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
297850ef999740f214a1990a9c090d3f3865d435aaMike Lockwoodnamespace android {
307850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood
3116864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpPacket::MtpPacket(int bufferSize)
3216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    :   mBuffer(NULL),
3316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mBufferSize(bufferSize),
3416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mAllocationIncrement(bufferSize),
3516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mPacketSize(0)
3616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood{
3716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer = (uint8_t *)malloc(bufferSize);
3816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (!mBuffer) {
3929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("out of memory!");
4016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        abort();
4116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    }
4216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
4316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
4416864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpPacket::~MtpPacket() {
4516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (mBuffer)
4616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        free(mBuffer);
4716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
4816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
4916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::reset() {
5016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    allocate(MTP_CONTAINER_HEADER_SIZE);
5116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mPacketSize = MTP_CONTAINER_HEADER_SIZE;
5216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    memset(mBuffer, 0, mBufferSize);
5316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
5416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
5516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::allocate(int length) {
5616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (length > mBufferSize) {
5716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        int newLength = length + mAllocationIncrement;
5816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mBuffer = (uint8_t *)realloc(mBuffer, newLength);
5916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        if (!mBuffer) {
6029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("out of memory!");
6116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood            abort();
6216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        }
6316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mBufferSize = newLength;
6416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    }
6516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
6616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
6716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::dump() {
68b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood#define DUMP_BYTES_PER_ROW  16
69b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood    char buffer[500];
70b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood    char* bufptr = buffer;
71b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood
7216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    for (int i = 0; i < mPacketSize; i++) {
73b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood        sprintf(bufptr, "%02X ", mBuffer[i]);
74b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood        bufptr += strlen(bufptr);
75b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood        if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
763856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("%s", buffer);
77b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood            bufptr = buffer;
78b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood        }
79b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood    }
80b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood    if (bufptr != buffer) {
81b14e588bec4d5e39e61b020b5b575f2ce555d316Mike Lockwood        // print last line
823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("%s", buffer);
8316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    }
843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("\n");
8516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
8616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
87f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwoodvoid MtpPacket::copyFrom(const MtpPacket& src) {
88f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    int length = src.mPacketSize;
89f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    allocate(length);
90f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    mPacketSize = length;
91f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    memcpy(mBuffer, src.mBuffer, length);
92f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood}
93f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood
9416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwooduint16_t MtpPacket::getUInt16(int offset) const {
9516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
9616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
9716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
9816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwooduint32_t MtpPacket::getUInt32(int offset) const {
9916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
10016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood           ((uint32_t)mBuffer[offset + 1] << 8)  | (uint32_t)mBuffer[offset];
10116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
10216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
10316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::putUInt16(int offset, uint16_t value) {
10416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)(value & 0xFF);
10516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
10616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
10716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
10816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::putUInt32(int offset, uint32_t value) {
10916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)(value & 0xFF);
11016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
11116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
11216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
11316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
11416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
11516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwooduint16_t MtpPacket::getContainerCode() const {
11616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    return getUInt16(MTP_CONTAINER_CODE_OFFSET);
11716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
11816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
11916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::setContainerCode(uint16_t code) {
12016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    putUInt16(MTP_CONTAINER_CODE_OFFSET, code);
12116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
12216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
123f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwooduint16_t MtpPacket::getContainerType() const {
124f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood    return getUInt16(MTP_CONTAINER_TYPE_OFFSET);
125f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood}
126f7454622eaac287d20ab43013d7015fe42b894f8Mike Lockwood
12716864bae0f51c32c456da2c43adf7a057c0c4882Mike LockwoodMtpTransactionID MtpPacket::getTransactionID() const {
12816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    return getUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET);
12916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
13016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
13116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::setTransactionID(MtpTransactionID id) {
13216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
13316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
13416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
13516864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwooduint32_t MtpPacket::getParameter(int index) const {
13616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (index < 1 || index > 5) {
13729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("index %d out of range in MtpPacket::getParameter", index);
13816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        return 0;
13916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    }
14016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    return getUInt32(MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t));
14116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
14216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
14316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwoodvoid MtpPacket::setParameter(int index, uint32_t value) {
14416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (index < 1 || index > 5) {
14529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("index %d out of range in MtpPacket::setParameter", index);
14616864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        return;
14716864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    }
14816864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    int offset = MTP_CONTAINER_PARAMETER_OFFSET + (index - 1) * sizeof(uint32_t);
14916864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    if (mPacketSize < offset + sizeof(uint32_t))
15016864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood        mPacketSize = offset + sizeof(uint32_t);
15116864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood    putUInt32(offset, value);
15216864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
15316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood
15416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#ifdef MTP_HOST
15542d0b79a787814d42e4c6f9dfe14f13cc0f6a758Mike Lockwoodint MtpPacket::transfer(struct usb_request* request) {
156126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood    int result = usb_device_bulk_transfer(request->dev,
157126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood                            request->endpoint,
158126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood                            request->buffer,
159126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood                            request->buffer_length,
160126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood                            0);
161126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood    request->actual_length = result;
162126ea73dd1919c8a176019c50b1ca96035aef45bMike Lockwood    return result;
16316864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood}
16416864bae0f51c32c456da2c43adf7a057c0c4882Mike Lockwood#endif
1657850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood
1667850ef999740f214a1990a9c090d3f3865d435aaMike Lockwood}  // namespace android
167