/*
 * 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;
}

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
