/*
 * 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 "MtpDevice"

#include "MtpDebug.h"
#include "MtpDevice.h"
#include "MtpDeviceInfo.h"
#include "MtpEventPacket.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpStorageInfo.h"
#include "MtpStringBuffer.h"
#include "MtpUtils.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <endian.h>

#include <usbhost/usbhost.h>

namespace android {

namespace {

static constexpr int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;

}  // namespace

#if 0
static bool isMtpDevice(uint16_t vendor, uint16_t product) {
    // Sandisk Sansa Fuze
    if (vendor == 0x0781 && product == 0x74c2)
        return true;
    // Samsung YP-Z5
    if (vendor == 0x04e8 && product == 0x503c)
        return true;
    return false;
}
#endif

namespace {

bool writeToFd(void* data, uint32_t /* unused_offset */, uint32_t length, void* clientData) {
    const int fd = *static_cast<int*>(clientData);
    const ssize_t result = write(fd, data, length);
    if (result < 0) {
        return false;
    }
    return static_cast<uint32_t>(result) == length;
}

}  // namespace

MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
    struct usb_device *device = usb_device_new(deviceName, fd);
    if (!device) {
        ALOGE("usb_device_new failed for %s", deviceName);
        return NULL;
    }

    struct usb_descriptor_header* desc;
    struct usb_descriptor_iter iter;

    usb_descriptor_iter_init(device, &iter);

    while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
        if (desc->bDescriptorType == USB_DT_INTERFACE) {
            struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;

            if (interface->bInterfaceClass == USB_CLASS_STILL_IMAGE &&
                interface->bInterfaceSubClass == 1 && // Still Image Capture
                interface->bInterfaceProtocol == 1)     // Picture Transfer Protocol (PIMA 15470)
            {
                char* manufacturerName = usb_device_get_manufacturer_name(device,
                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                char* productName = usb_device_get_product_name(device,
                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                ALOGD("Found camera: \"%s\" \"%s\"\n", manufacturerName, productName);
                free(manufacturerName);
                free(productName);
            } else if (interface->bInterfaceClass == 0xFF &&
                    interface->bInterfaceSubClass == 0xFF &&
                    interface->bInterfaceProtocol == 0) {
                char* interfaceName = usb_device_get_string(device, interface->iInterface,
                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                if (!interfaceName) {
                    continue;
                } else if (strcmp(interfaceName, "MTP")) {
                    free(interfaceName);
                    continue;
                }
                free(interfaceName);

                // Looks like an android style MTP device
                char* manufacturerName = usb_device_get_manufacturer_name(device,
                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                char* productName = usb_device_get_product_name(device,
                        USB_CONTROL_TRANSFER_TIMEOUT_MS);
                ALOGD("Found MTP device: \"%s\" \"%s\"\n", manufacturerName, productName);
                free(manufacturerName);
                free(productName);
            }
#if 0
             else {
                // look for special cased devices based on vendor/product ID
                // we are doing this mainly for testing purposes
                uint16_t vendor = usb_device_get_vendor_id(device);
                uint16_t product = usb_device_get_product_id(device);
                if (!isMtpDevice(vendor, product)) {
                    // not an MTP or PTP device
                    continue;
                }
                // request MTP OS string and descriptor
                // some music players need to see this before entering MTP mode.
                char buffer[256];
                memset(buffer, 0, sizeof(buffer));
                int ret = usb_device_control_transfer(device,
                        USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_STANDARD,
                        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) | 0xEE,
                        0, buffer, sizeof(buffer), 0);
                printf("usb_device_control_transfer returned %d errno: %d\n", ret, errno);
                if (ret > 0) {
                    printf("got MTP string %s\n", buffer);
                    ret = usb_device_control_transfer(device,
                            USB_DIR_IN|USB_RECIP_DEVICE|USB_TYPE_VENDOR, 1,
                            0, 4, buffer, sizeof(buffer), 0);
                    printf("OS descriptor got %d\n", ret);
                } else {
                    printf("no MTP string\n");
                }
            }
#else
            else {
                continue;
            }
#endif
            // if we got here, then we have a likely MTP or PTP device

            // interface should be followed by three endpoints
            struct usb_endpoint_descriptor *ep;
            struct usb_endpoint_descriptor *ep_in_desc = NULL;
            struct usb_endpoint_descriptor *ep_out_desc = NULL;
            struct usb_endpoint_descriptor *ep_intr_desc = NULL;
            //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor;
            struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL;
            for (int i = 0; i < 3; i++) {
                ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
                if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) {
                    ALOGD("Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n");
                    ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep;
                    ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
                 }

                if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
                    ALOGE("endpoints not found\n");
                    usb_device_close(device);
                    return NULL;
                }

                if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
                    if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
                        ep_in_desc = ep;
                    else
                        ep_out_desc = ep;
                } else if (ep->bmAttributes == USB_ENDPOINT_XFER_INT &&
                    ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
                    ep_intr_desc = ep;
                }
            }
            if (!ep_in_desc || !ep_out_desc || !ep_intr_desc) {
                ALOGE("endpoints not found\n");
                usb_device_close(device);
                return NULL;
            }

            int ret = usb_device_claim_interface(device, interface->bInterfaceNumber);
            if (ret && errno == EBUSY) {
                // disconnect kernel driver and try again
                usb_device_connect_kernel_driver(device, interface->bInterfaceNumber, false);
                ret = usb_device_claim_interface(device, interface->bInterfaceNumber);
            }
            if (ret) {
                ALOGE("usb_device_claim_interface failed errno: %d\n", errno);
                usb_device_close(device);
                return NULL;
            }

            MtpDevice* mtpDevice = new MtpDevice(device, interface->bInterfaceNumber,
                        ep_in_desc, ep_out_desc, ep_intr_desc);
            mtpDevice->initialize();
            return mtpDevice;
        }
    }

    usb_device_close(device);
    ALOGE("device not found");
    return NULL;
}

MtpDevice::MtpDevice(struct usb_device* device, int interface,
            const struct usb_endpoint_descriptor *ep_in,
            const struct usb_endpoint_descriptor *ep_out,
            const struct usb_endpoint_descriptor *ep_intr)
    :   mDevice(device),
        mInterface(interface),
        mRequestIn1(NULL),
        mRequestIn2(NULL),
        mRequestOut(NULL),
        mRequestIntr(NULL),
        mDeviceInfo(NULL),
        mSessionID(0),
        mTransactionID(0),
        mReceivedResponse(false),
        mProcessingEvent(false),
        mCurrentEventHandle(0),
        mLastSendObjectInfoTransactionID(0),
        mLastSendObjectInfoObjectHandle(0),
        mPacketDivisionMode(FIRST_PACKET_HAS_PAYLOAD)
{
    mRequestIn1 = usb_request_new(device, ep_in);
    mRequestIn2 = usb_request_new(device, ep_in);
    mRequestOut = usb_request_new(device, ep_out);
    mRequestIntr = usb_request_new(device, ep_intr);
}

MtpDevice::~MtpDevice() {
    close();
    for (size_t i = 0; i < mDeviceProperties.size(); i++)
        delete mDeviceProperties[i];
    usb_request_free(mRequestIn1);
    usb_request_free(mRequestIn2);
    usb_request_free(mRequestOut);
    usb_request_free(mRequestIntr);
}

void MtpDevice::initialize() {
    openSession();
    mDeviceInfo = getDeviceInfo();
    if (mDeviceInfo) {
        if (mDeviceInfo->mDeviceProperties) {
            int count = mDeviceInfo->mDeviceProperties->size();
            for (int i = 0; i < count; i++) {
                MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
                MtpProperty* property = getDevicePropDesc(propCode);
                if (property)
                    mDeviceProperties.push_back(property);
            }
        }
    }
}

void MtpDevice::close() {
    if (mDevice) {
        usb_device_release_interface(mDevice, mInterface);
        usb_device_close(mDevice);
        mDevice = NULL;
    }
}

void MtpDevice::print() {
    if (!mDeviceInfo)
        return;

    mDeviceInfo->print();

    if (mDeviceInfo->mDeviceProperties) {
        ALOGI("***** DEVICE PROPERTIES *****\n");
        int count = mDeviceInfo->mDeviceProperties->size();
        for (int i = 0; i < count; i++) {
            MtpDeviceProperty propCode = (*mDeviceInfo->mDeviceProperties)[i];
            MtpProperty* property = getDevicePropDesc(propCode);
            if (property) {
                property->print();
                delete property;
            }
        }
    }

    if (mDeviceInfo->mPlaybackFormats) {
            ALOGI("***** OBJECT PROPERTIES *****\n");
        int count = mDeviceInfo->mPlaybackFormats->size();
        for (int i = 0; i < count; i++) {
            MtpObjectFormat format = (*mDeviceInfo->mPlaybackFormats)[i];
            ALOGI("*** FORMAT: %s\n", MtpDebug::getFormatCodeName(format));
            MtpObjectPropertyList* props = getObjectPropsSupported(format);
            if (props) {
                for (size_t j = 0; j < props->size(); j++) {
                    MtpObjectProperty prop = (*props)[j];
                    MtpProperty* property = getObjectPropDesc(prop, format);
                    if (property) {
                        property->print();
                        delete property;
                    } else {
                        ALOGE("could not fetch property: %s",
                                MtpDebug::getObjectPropCodeName(prop));
                    }
                }
            }
        }
    }
}

const char* MtpDevice::getDeviceName() {
    if (mDevice)
        return usb_device_get_name(mDevice);
    else
        return "???";
}

bool MtpDevice::openSession() {
    std::lock_guard<std::mutex> lg(mMutex);

    mSessionID = 0;
    mTransactionID = 0;
    MtpSessionID newSession = 1;
    mRequest.reset();
    mRequest.setParameter(1, newSession);
    if (!sendRequest(MTP_OPERATION_OPEN_SESSION))
        return false;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_SESSION_ALREADY_OPEN)
        newSession = mResponse.getParameter(1);
    else if (ret != MTP_RESPONSE_OK)
        return false;

    mSessionID = newSession;
    mTransactionID = 1;
    return true;
}

bool MtpDevice::closeSession() {
    // FIXME
    return true;
}

MtpDeviceInfo* MtpDevice::getDeviceInfo() {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    if (!sendRequest(MTP_OPERATION_GET_DEVICE_INFO))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        MtpDeviceInfo* info = new MtpDeviceInfo;
        if (info->read(mData))
            return info;
        else
            delete info;
    }
    return NULL;
}

MtpStorageIDList* MtpDevice::getStorageIDs() {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    if (!sendRequest(MTP_OPERATION_GET_STORAGE_IDS))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        return mData.getAUInt32();
    }
    return NULL;
}

MtpStorageInfo* MtpDevice::getStorageInfo(MtpStorageID storageID) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, storageID);
    if (!sendRequest(MTP_OPERATION_GET_STORAGE_INFO))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        MtpStorageInfo* info = new MtpStorageInfo(storageID);
        if (info->read(mData))
            return info;
        else
            delete info;
    }
    return NULL;
}

MtpObjectHandleList* MtpDevice::getObjectHandles(MtpStorageID storageID,
            MtpObjectFormat format, MtpObjectHandle parent) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, storageID);
    mRequest.setParameter(2, format);
    mRequest.setParameter(3, parent);
    if (!sendRequest(MTP_OPERATION_GET_OBJECT_HANDLES))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        return mData.getAUInt32();
    }
    return NULL;
}

MtpObjectInfo* MtpDevice::getObjectInfo(MtpObjectHandle handle) {
    std::lock_guard<std::mutex> lg(mMutex);

    // FIXME - we might want to add some caching here

    mRequest.reset();
    mRequest.setParameter(1, handle);
    if (!sendRequest(MTP_OPERATION_GET_OBJECT_INFO))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        MtpObjectInfo* info = new MtpObjectInfo(handle);
        if (info->read(mData))
            return info;
        else
            delete info;
    }
    return NULL;
}

void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
        MtpResponseCode ret = readResponse();
        if (ret == MTP_RESPONSE_OK) {
            return mData.getData(&outLength);
        }
    }
    outLength = 0;
    return NULL;
}

MtpObjectHandle MtpDevice::sendObjectInfo(MtpObjectInfo* info) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    MtpObjectHandle parent = info->mParent;
    if (parent == 0)
        parent = MTP_PARENT_ROOT;

    mRequest.setParameter(1, info->mStorageID);
    mRequest.setParameter(2, parent);

    mData.reset();
    mData.putUInt32(info->mStorageID);
    mData.putUInt16(info->mFormat);
    mData.putUInt16(info->mProtectionStatus);
    mData.putUInt32(info->mCompressedSize);
    mData.putUInt16(info->mThumbFormat);
    mData.putUInt32(info->mThumbCompressedSize);
    mData.putUInt32(info->mThumbPixWidth);
    mData.putUInt32(info->mThumbPixHeight);
    mData.putUInt32(info->mImagePixWidth);
    mData.putUInt32(info->mImagePixHeight);
    mData.putUInt32(info->mImagePixDepth);
    mData.putUInt32(info->mParent);
    mData.putUInt16(info->mAssociationType);
    mData.putUInt32(info->mAssociationDesc);
    mData.putUInt32(info->mSequenceNumber);
    mData.putString(info->mName);

    char created[100], modified[100];
    formatDateTime(info->mDateCreated, created, sizeof(created));
    formatDateTime(info->mDateModified, modified, sizeof(modified));

    mData.putString(created);
    mData.putString(modified);
    if (info->mKeywords)
        mData.putString(info->mKeywords);
    else
        mData.putEmptyString();

   if (sendRequest(MTP_OPERATION_SEND_OBJECT_INFO) && sendData()) {
        MtpResponseCode ret = readResponse();
        if (ret == MTP_RESPONSE_OK) {
            mLastSendObjectInfoTransactionID = mRequest.getTransactionID();
            mLastSendObjectInfoObjectHandle = mResponse.getParameter(3);
            info->mStorageID = mResponse.getParameter(1);
            info->mParent = mResponse.getParameter(2);
            info->mHandle = mResponse.getParameter(3);
            return info->mHandle;
        }
    }
    return (MtpObjectHandle)-1;
}

bool MtpDevice::sendObject(MtpObjectHandle handle, uint32_t size, int srcFD) {
    std::lock_guard<std::mutex> lg(mMutex);

    if (mLastSendObjectInfoTransactionID + 1 != mTransactionID ||
            mLastSendObjectInfoObjectHandle != handle) {
        ALOGE("A sendObject request must follow the sendObjectInfo request.");
        return false;
    }

    mRequest.reset();
    if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
        mData.setOperationCode(mRequest.getOperationCode());
        mData.setTransactionID(mRequest.getTransactionID());
        const int64_t writeResult = mData.write(mRequestOut, mPacketDivisionMode, srcFD, size);
        const MtpResponseCode ret = readResponse();
        return ret == MTP_RESPONSE_OK && writeResult > 0;
    }
    return false;
}

bool MtpDevice::deleteObject(MtpObjectHandle handle) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    if (sendRequest(MTP_OPERATION_DELETE_OBJECT)) {
        MtpResponseCode ret = readResponse();
        if (ret == MTP_RESPONSE_OK)
            return true;
    }
    return false;
}

MtpObjectHandle MtpDevice::getParent(MtpObjectHandle handle) {
    MtpObjectInfo* info = getObjectInfo(handle);
    if (info) {
        MtpObjectHandle parent = info->mParent;
        delete info;
        return parent;
    } else {
        return -1;
    }
}

MtpObjectHandle MtpDevice::getStorageID(MtpObjectHandle handle) {
    MtpObjectInfo* info = getObjectInfo(handle);
    if (info) {
        MtpObjectHandle storageId = info->mStorageID;
        delete info;
        return storageId;
    } else {
        return -1;
    }
}

MtpObjectPropertyList* MtpDevice::getObjectPropsSupported(MtpObjectFormat format) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, format);
    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        return mData.getAUInt16();
    }
    return NULL;

}

MtpProperty* MtpDevice::getDevicePropDesc(MtpDeviceProperty code) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, code);
    if (!sendRequest(MTP_OPERATION_GET_DEVICE_PROP_DESC))
        return NULL;
    if (!readData())
        return NULL;
    MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        MtpProperty* property = new MtpProperty;
        if (property->read(mData))
            return property;
        else
            delete property;
    }
    return NULL;
}

bool MtpDevice::setDevicePropValueStr(MtpProperty* property) {
    if (property == nullptr)
        return false;

    std::lock_guard<std::mutex> lg(mMutex);

    if (property->getDataType() != MTP_TYPE_STR) {
        return false;
    }

    mRequest.reset();
    mRequest.setParameter(1, property->getPropertyCode());

    mData.reset();
    mData.putString(property->getCurrentValue().str);

   if (sendRequest(MTP_OPERATION_SET_DEVICE_PROP_VALUE) && sendData()) {
        MtpResponseCode ret = readResponse();
        if (ret != MTP_RESPONSE_OK) {
            ALOGW("%s: Response=0x%04X\n", __func__, ret);
            return false;
        }
    }
    return true;
}

MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, code);
    mRequest.setParameter(2, format);
    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_DESC))
        return NULL;
    if (!readData())
        return NULL;
    const MtpResponseCode ret = readResponse();
    if (ret == MTP_RESPONSE_OK) {
        MtpProperty* property = new MtpProperty;
        if (property->read(mData))
            return property;
        else
            delete property;
    }
    return NULL;
}

bool MtpDevice::getObjectPropValue(MtpObjectHandle handle, MtpProperty* property) {
    if (property == nullptr)
        return false;

    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    mRequest.setParameter(2, property->getPropertyCode());
    if (!sendRequest(MTP_OPERATION_GET_OBJECT_PROP_VALUE))
        return false;
    if (!readData())
        return false;
    if (readResponse() != MTP_RESPONSE_OK)
        return false;
    property->setCurrentValue(mData);
    return true;
}

bool MtpDevice::readObject(MtpObjectHandle handle,
                           ReadObjectCallback callback,
                           uint32_t expectedLength,
                           void* clientData) {
    return readObjectInternal(handle, callback, &expectedLength, clientData);
}

// reads the object's data and writes it to the specified file path
bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
    ALOGD("readObject: %s", destPath);
    int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        ALOGE("open failed for %s", destPath);
        return false;
    }

    fchown(fd, getuid(), group);
    // set permissions
    int mask = umask(0);
    fchmod(fd, perm);
    umask(mask);

    bool result = readObject(handle, fd);
    ::close(fd);
    return result;
}

bool MtpDevice::readObject(MtpObjectHandle handle, int fd) {
    ALOGD("readObject: %d", fd);
    return readObjectInternal(handle, writeToFd, NULL /* expected size */, &fd);
}

bool MtpDevice::readObjectInternal(MtpObjectHandle handle,
                                   ReadObjectCallback callback,
                                   const uint32_t* expectedLength,
                                   void* clientData) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
        ALOGE("Failed to send a read request.");
        return false;
    }

    return readData(callback, expectedLength, nullptr, clientData);
}

bool MtpDevice::readData(ReadObjectCallback callback,
                            const uint32_t* expectedLength,
                            uint32_t* writtenSize,
                            void* clientData) {
    if (!mData.readDataHeader(mRequestIn1)) {
        ALOGE("Failed to read header.");
        return false;
    }

    // If object size 0 byte, the remote device may reply a response packet without sending any data
    // packets.
    if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
        mResponse.copyFrom(mData);
        return mResponse.getResponseCode() == MTP_RESPONSE_OK;
    }

    const uint32_t fullLength = mData.getContainerLength();
    if (fullLength < MTP_CONTAINER_HEADER_SIZE) {
        ALOGE("fullLength is too short: %d", fullLength);
        return false;
    }
    const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
    if (expectedLength && length != *expectedLength) {
        ALOGE("readObject error length: %d", fullLength);
        return false;
    }

    uint32_t offset = 0;
    bool writingError = false;

    {
        int initialDataLength = 0;
        void* const initialData = mData.getData(&initialDataLength);
        if (fullLength > MTP_CONTAINER_HEADER_SIZE && initialDataLength == 0) {
            // According to the MTP spec, the responder (MTP device) can choose two ways of sending
            // data. a) The first packet contains the head and as much of the payload as possible
            // b) The first packet contains only the header. The initiator (MTP host) needs
            // to remember which way the responder used, and send upcoming data in the same way.
            ALOGD("Found short packet that contains only a header.");
            mPacketDivisionMode = FIRST_PACKET_ONLY_HEADER;
        }
        if (initialData) {
            if (initialDataLength > 0) {
                if (!callback(initialData, offset, initialDataLength, clientData)) {
                    ALOGE("Failed to write initial data.");
                    writingError = true;
                }
                offset += initialDataLength;
            }
            free(initialData);
        }
    }

    // USB reads greater than 16K don't work.
    char buffer1[MTP_BUFFER_SIZE], buffer2[MTP_BUFFER_SIZE];
    mRequestIn1->buffer = buffer1;
    mRequestIn2->buffer = buffer2;
    struct usb_request* req = NULL;

    while (offset < length) {
        // Wait for previous read to complete.
        void* writeBuffer = NULL;
        int writeLength = 0;
        if (req) {
            const int read = mData.readDataWait(mDevice);
            if (read < 0) {
                ALOGE("readDataWait failed.");
                return false;
            }
            writeBuffer = req->buffer;
            writeLength = read;
        }

        // Request to read next chunk.
        const uint32_t nextOffset = offset + writeLength;
        if (nextOffset < length) {
            // Queue up a read request.
            const size_t remaining = length - nextOffset;
            req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
            req->buffer_length = remaining > MTP_BUFFER_SIZE ?
                    static_cast<size_t>(MTP_BUFFER_SIZE) : remaining;
            if (mData.readDataAsync(req) != 0) {
                ALOGE("readDataAsync failed");
                return false;
            }
        }

        // Write previous buffer.
        if (writeBuffer && !writingError) {
            if (!callback(writeBuffer, offset, writeLength, clientData)) {
                ALOGE("write failed");
                writingError = true;
            }
        }
        offset = nextOffset;
    }

    if (writtenSize) {
        *writtenSize = length;
    }

    return readResponse() == MTP_RESPONSE_OK;
}

bool MtpDevice::readPartialObject(MtpObjectHandle handle,
                                  uint32_t offset,
                                  uint32_t size,
                                  uint32_t *writtenSize,
                                  ReadObjectCallback callback,
                                  void* clientData) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    mRequest.setParameter(2, offset);
    mRequest.setParameter(3, size);
    if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT)) {
        ALOGE("Failed to send a read request.");
        return false;
    }
    // The expected size is null because it requires the exact number of bytes to read though
    // MTP_OPERATION_GET_PARTIAL_OBJECT allows devices to return shorter length of bytes than
    // requested. Destination's buffer length should be checked in |callback|.
    return readData(callback, nullptr /* expected size */, writtenSize, clientData);
}

bool MtpDevice::readPartialObject64(MtpObjectHandle handle,
                                    uint64_t offset,
                                    uint32_t size,
                                    uint32_t *writtenSize,
                                    ReadObjectCallback callback,
                                    void* clientData) {
    std::lock_guard<std::mutex> lg(mMutex);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    mRequest.setParameter(2, 0xffffffff & offset);
    mRequest.setParameter(3, 0xffffffff & (offset >> 32));
    mRequest.setParameter(4, size);
    if (!sendRequest(MTP_OPERATION_GET_PARTIAL_OBJECT_64)) {
        ALOGE("Failed to send a read request.");
        return false;
    }
    // The expected size is null because it requires the exact number of bytes to read though
    // MTP_OPERATION_GET_PARTIAL_OBJECT_64 allows devices to return shorter length of bytes than
    // requested. Destination's buffer length should be checked in |callback|.
    return readData(callback, nullptr /* expected size */, writtenSize, clientData);
}

bool MtpDevice::sendRequest(MtpOperationCode operation) {
    ALOGV("sendRequest: %s\n", MtpDebug::getOperationCodeName(operation));
    mReceivedResponse = false;
    mRequest.setOperationCode(operation);
    if (mTransactionID > 0)
        mRequest.setTransactionID(mTransactionID++);
    int ret = mRequest.write(mRequestOut);
    mRequest.dump();
    return (ret > 0);
}

bool MtpDevice::sendData() {
    ALOGV("sendData\n");
    mData.setOperationCode(mRequest.getOperationCode());
    mData.setTransactionID(mRequest.getTransactionID());
    int ret = mData.write(mRequestOut, mPacketDivisionMode);
    mData.dump();
    return (ret >= 0);
}

bool MtpDevice::readData() {
    mData.reset();
    int ret = mData.read(mRequestIn1);
    ALOGV("readData returned %d\n", ret);
    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
        if (mData.getContainerType() == MTP_CONTAINER_TYPE_RESPONSE) {
            ALOGD("got response packet instead of data packet");
            // we got a response packet rather than data
            // copy it to mResponse
            mResponse.copyFrom(mData);
            mReceivedResponse = true;
            return false;
        }
        mData.dump();
        return true;
    }
    else {
        ALOGV("readResponse failed\n");
        return false;
    }
}

MtpResponseCode MtpDevice::readResponse() {
    ALOGV("readResponse\n");
    if (mReceivedResponse) {
        mReceivedResponse = false;
        return mResponse.getResponseCode();
    }
    int ret = mResponse.read(mRequestIn1);
    // handle zero length packets, which might occur if the data transfer
    // ends on a packet boundary
    if (ret == 0)
        ret = mResponse.read(mRequestIn1);
    if (ret >= MTP_CONTAINER_HEADER_SIZE) {
        mResponse.dump();
        return mResponse.getResponseCode();
    } else {
        ALOGD("readResponse failed\n");
        return -1;
    }
}

int MtpDevice::submitEventRequest() {
    if (!mEventMutex.try_lock()) {
        // An event is being reaped on another thread.
        return -1;
    }
    if (mProcessingEvent) {
        // An event request was submitted, but no reapEventRequest called so far.
        return -1;
    }
    std::lock_guard<std::mutex> lg(mEventMutexForInterrupt);
    mEventPacket.sendRequest(mRequestIntr);
    const int currentHandle = ++mCurrentEventHandle;
    mProcessingEvent = true;
    mEventMutex.unlock();
    return currentHandle;
}

int MtpDevice::reapEventRequest(int handle, uint32_t (*parameters)[3]) {
    std::lock_guard<std::mutex> lg(mEventMutex);
    if (!mProcessingEvent || mCurrentEventHandle != handle || !parameters) {
        return -1;
    }
    mProcessingEvent = false;
    const int readSize = mEventPacket.readResponse(mRequestIntr->dev);
    const int result = mEventPacket.getEventCode();
    // MTP event has three parameters.
    (*parameters)[0] = mEventPacket.getParameter(1);
    (*parameters)[1] = mEventPacket.getParameter(2);
    (*parameters)[2] = mEventPacket.getParameter(3);
    return readSize != 0 ? result : 0;
}

void MtpDevice::discardEventRequest(int handle) {
    std::lock_guard<std::mutex> lg(mEventMutexForInterrupt);
    if (mCurrentEventHandle != handle) {
        return;
    }
    usb_request_cancel(mRequestIntr);
}

}  // namespace android
