Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1492e5b1 authored by Daichi Hirono's avatar Daichi Hirono Committed by Android (Google) Code Review
Browse files

Merge "Use common implementation for getObject and importFile."

parents 6a84e6dc 4fd9a8b9
Loading
Loading
Loading
Loading
+3 −5
Original line number Original line Diff line number Diff line
@@ -25,8 +25,6 @@
#include "MtpDataPacket.h"
#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
#include "MtpStringBuffer.h"


#define MTP_BUFFER_SIZE 16384

namespace android {
namespace android {


MtpDataPacket::MtpDataPacket()
MtpDataPacket::MtpDataPacket()
@@ -540,17 +538,17 @@ int MtpDataPacket::write(struct usb_request *request, void* buffer, uint32_t len


#endif // MTP_HOST
#endif // MTP_HOST


void* MtpDataPacket::getData(int& outLength) const {
void* MtpDataPacket::getData(int* outLength) const {
    int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
    int length = mPacketSize - MTP_CONTAINER_HEADER_SIZE;
    if (length > 0) {
    if (length > 0) {
        void* result = malloc(length);
        void* result = malloc(length);
        if (result) {
        if (result) {
            memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
            memcpy(result, mBuffer + MTP_CONTAINER_HEADER_SIZE, length);
            outLength = length;
            *outLength = length;
            return result;
            return result;
        }
        }
    }
    }
    outLength = 0;
    *outLength = 0;
    return NULL;
    return NULL;
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -117,7 +117,7 @@ public:


    inline bool         hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
    inline bool         hasData() const { return mPacketSize > MTP_CONTAINER_HEADER_SIZE; }
    inline uint32_t     getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
    inline uint32_t     getContainerLength() const { return MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET); }
    void*               getData(int& outLength) const;
    void*               getData(int* outLength) const;
};
};


}; // namespace android
}; // namespace android
+81 −143
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#include "MtpDebug.h"
#include "MtpDebug.h"
#include "MtpDevice.h"
#include "MtpDevice.h"
#include "MtpDeviceInfo.h"
#include "MtpDeviceInfo.h"
#include "MtpEventPacket.h"
#include "MtpObjectInfo.h"
#include "MtpObjectInfo.h"
#include "MtpProperty.h"
#include "MtpProperty.h"
#include "MtpStorageInfo.h"
#include "MtpStorageInfo.h"
@@ -50,6 +51,15 @@ static bool isMtpDevice(uint16_t vendor, uint16_t product) {
}
}
#endif
#endif


namespace {

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

}

MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
MtpDevice* MtpDevice::open(const char* deviceName, int fd) {
    struct usb_device *device = usb_device_new(deviceName, fd);
    struct usb_device *device = usb_device_new(deviceName, fd);
    if (!device) {
    if (!device) {
@@ -414,7 +424,7 @@ void* MtpDevice::getThumbnail(MtpObjectHandle handle, int& outLength) {
    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
    if (sendRequest(MTP_OPERATION_GET_THUMB) && readData()) {
        MtpResponseCode ret = readResponse();
        MtpResponseCode ret = readResponse();
        if (ret == MTP_RESPONSE_OK) {
        if (ret == MTP_RESPONSE_OK) {
            return mData.getData(outLength);
            return mData.getData(&outLength);
        }
        }
    }
    }
    outLength = 0;
    outLength = 0;
@@ -593,94 +603,10 @@ MtpProperty* MtpDevice::getObjectPropDesc(MtpObjectProperty code, MtpObjectForma
}
}


bool MtpDevice::readObject(MtpObjectHandle handle,
bool MtpDevice::readObject(MtpObjectHandle handle,
        bool (* callback)(void* data, int offset, int length, void* clientData),
                           ReadObjectCallback callback,
        size_t objectSize, void* clientData) {
                           size_t expectedLength,
    Mutex::Autolock autoLock(mMutex);
                           void* clientData) {
    bool result = false;
    return readObjectInternal(handle, callback, &expectedLength, clientData);

    mRequest.reset();
    mRequest.setParameter(1, handle);
    if (sendRequest(MTP_OPERATION_GET_OBJECT)
            && mData.readDataHeader(mRequestIn1)) {
        uint32_t length = mData.getContainerLength();
        if (length - MTP_CONTAINER_HEADER_SIZE != objectSize) {
            ALOGE("readObject error objectSize: %d, length: %d",
                    objectSize, length);
            goto fail;
        }
        length -= MTP_CONTAINER_HEADER_SIZE;
        uint32_t remaining = length;
        int offset = 0;

        int initialDataLength = 0;
        void* initialData = mData.getData(initialDataLength);
        if (initialData) {
            if (initialDataLength > 0) {
                if (!callback(initialData, 0, initialDataLength, clientData))
                    goto fail;
                remaining -= initialDataLength;
                offset += initialDataLength;
            }
            free(initialData);
        }

        // USB reads greater than 16K don't work
        char buffer1[16384], buffer2[16384];
        mRequestIn1->buffer = buffer1;
        mRequestIn2->buffer = buffer2;
        struct usb_request* req = mRequestIn1;
        void* writeBuffer = NULL;
        int writeLength = 0;

        while (remaining > 0 || writeBuffer) {
            if (remaining > 0) {
                // queue up a read request
                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
                if (mData.readDataAsync(req)) {
                    ALOGE("readDataAsync failed");
                    goto fail;
                }
            } else {
                req = NULL;
            }

            if (writeBuffer) {
                // write previous buffer
                if (!callback(writeBuffer, offset, writeLength, clientData)) {
                    ALOGE("write failed");
                    // wait for pending read before failing
                    if (req)
                        mData.readDataWait(mDevice);
                    goto fail;
                }
                offset += writeLength;
                writeBuffer = NULL;
            }

            // wait for read to complete
            if (req) {
                int read = mData.readDataWait(mDevice);
                if (read < 0)
                    goto fail;

                if (read > 0) {
                    writeBuffer = req->buffer;
                    writeLength = read;
                    remaining -= read;
                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
                } else {
                    writeBuffer = NULL;
                }
            }
        }

        MtpResponseCode response = readResponse();
        if (response == MTP_RESPONSE_OK)
            result = true;
    }

fail:
    return result;
}
}


// reads the object's data and writes it to the specified file path
// reads the object's data and writes it to the specified file path
@@ -705,86 +631,98 @@ bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int gro


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


bool MtpDevice::readObjectInternal(MtpObjectHandle handle,
                                   ReadObjectCallback callback,
                                   const size_t* expectedLength,
                                   void* clientData) {
    Mutex::Autolock autoLock(mMutex);
    Mutex::Autolock autoLock(mMutex);


    mRequest.reset();
    mRequest.reset();
    mRequest.setParameter(1, handle);
    mRequest.setParameter(1, handle);
    if (sendRequest(MTP_OPERATION_GET_OBJECT) && mData.readDataHeader(mRequestIn1)) {
    if (!sendRequest(MTP_OPERATION_GET_OBJECT)) {
        uint32_t length = mData.getContainerLength();
        ALOGE("Failed to send a read request.");
        if (length < MTP_CONTAINER_HEADER_SIZE) {
        return false;
            ALOGE("Invalid container length.");
    }

    if (!mData.readDataHeader(mRequestIn1)) {
        ALOGE("Failed to read header.");
        return false;
    }

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


    const uint32_t length = fullLength - MTP_CONTAINER_HEADER_SIZE;
    uint32_t offset = 0;
    bool writingError = false;
    bool writingError = false;

    {
        int initialDataLength = 0;
        int initialDataLength = 0;
        void* initialData = mData.getData(initialDataLength);
        void* const initialData = mData.getData(&initialDataLength);
        if (initialData) {
        if (initialData) {
            if (initialDataLength > 0) {
            if (initialDataLength > 0) {
                if (write(fd, initialData, initialDataLength) != initialDataLength) {
                if (!callback(initialData, offset, initialDataLength, clientData)) {
                    ALOGE("Failed to write initial data.");
                    ALOGE("Failed to write initial data.");
                    writingError = true;
                    writingError = true;
                }
                }
                remaining -= initialDataLength;
                offset += initialDataLength;
            }
            }
            free(initialData);
            free(initialData);
        }
        }
    }


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

    while (offset < length) {
        // Wait for previous read to complete.
        void* writeBuffer = NULL;
        void* writeBuffer = NULL;
        int writeLength = 0;
        int writeLength = 0;

        while (remaining > 0 || writeBuffer) {
            if (remaining > 0) {
                // queue up a read request
                req->buffer_length = (remaining > sizeof(buffer1) ? sizeof(buffer1) : remaining);
                if (mData.readDataAsync(req)) {
                    ALOGE("readDataAsync failed");
                    return false;
                }
            } else {
                req = NULL;
            }

            if (writeBuffer && !writingError) {
                // write previous buffer
                if (write(fd, writeBuffer, writeLength) != writeLength) {
                    writingError = true;
                }
            }
            writeBuffer = NULL;

            // wait for read to complete
        if (req) {
        if (req) {
                int read = mData.readDataWait(mDevice);
            const int read = mData.readDataWait(mDevice);
            if (read < 0) {
            if (read < 0) {
                ALOGE("readDataWait failed.");
                ALOGE("readDataWait failed.");
                return false;
                return false;
            }
            }

                if (read > 0) {
            writeBuffer = req->buffer;
            writeBuffer = req->buffer;
            writeLength = read;
            writeLength = read;
                    remaining -= read;
                    req = (req == mRequestIn1 ? mRequestIn2 : mRequestIn1);
                } else {
                    writeBuffer = NULL;
        }
        }

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


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


    return false;
    return readResponse() == MTP_RESPONSE_OK && !writingError;
}
}


bool MtpDevice::sendRequest(MtpOperationCode operation) {
bool MtpDevice::sendRequest(MtpOperationCode operation) {
+5 −3
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ private:
    Mutex                   mMutex;
    Mutex                   mMutex;


public:
public:
    typedef bool (*ReadObjectCallback)(void* data, int offset, int length, void* clientData);
                            MtpDevice(struct usb_device* device, int interface,
                            MtpDevice(struct usb_device* device, int interface,
                                    const struct usb_endpoint_descriptor *ep_in,
                                    const struct usb_endpoint_descriptor *ep_in,
                                    const struct usb_endpoint_descriptor *ep_out,
                                    const struct usb_endpoint_descriptor *ep_out,
@@ -95,15 +96,16 @@ public:
    MtpProperty*            getDevicePropDesc(MtpDeviceProperty code);
    MtpProperty*            getDevicePropDesc(MtpDeviceProperty code);
    MtpProperty*            getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);
    MtpProperty*            getObjectPropDesc(MtpObjectProperty code, MtpObjectFormat format);


    bool                    readObject(MtpObjectHandle handle,
    bool                    readObject(MtpObjectHandle handle, ReadObjectCallback callback,
                                    bool (* callback)(void* data, int offset,
                                            int length, void* clientData),
                                    size_t objectSize, void* clientData);
                                    size_t objectSize, void* clientData);
    bool                    readObject(MtpObjectHandle handle, const char* destPath, int group,
    bool                    readObject(MtpObjectHandle handle, const char* destPath, int group,
                                    int perm);
                                    int perm);
    bool                    readObject(MtpObjectHandle handle, int fd);
    bool                    readObject(MtpObjectHandle handle, int fd);


private:
private:
    // If |objectSize| is not NULL, it checks object size before reading data bytes.
    bool                    readObjectInternal(MtpObjectHandle handle, ReadObjectCallback callback,
                                     const size_t* objectSize, void* clientData);
    bool                    sendRequest(MtpOperationCode operation);
    bool                    sendRequest(MtpOperationCode operation);
    bool                    sendData();
    bool                    sendData();
    bool                    readData();
    bool                    readData();
+3 −0
Original line number Original line Diff line number Diff line
@@ -37,6 +37,9 @@
#define MTP_CONTAINER_PARAMETER_OFFSET          12
#define MTP_CONTAINER_PARAMETER_OFFSET          12
#define MTP_CONTAINER_HEADER_SIZE               12
#define MTP_CONTAINER_HEADER_SIZE               12


// Maximum buffer size for a MTP packet.
#define MTP_BUFFER_SIZE 16384

// MTP Data Types
// MTP Data Types
#define MTP_TYPE_UNDEFINED      0x0000          // Undefined
#define MTP_TYPE_UNDEFINED      0x0000          // Undefined
#define MTP_TYPE_INT8           0x0001          // Signed 8-bit integer
#define MTP_TYPE_INT8           0x0001          // Signed 8-bit integer