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

Commit 297912b6 authored by Jerry Zhang's avatar Jerry Zhang
Browse files

Remove limitation on read/write size

Previously ios called through read write
were limited to 16kb because read packets
are very small. However, write packets can
be greater than that amount in cases where
a folder contains over 4k items. Thus,
remove the limitation.

Add corresponding ReadLarge and WriteLarge
tests as well.

Bug: 79214960
Test: mtp_ffs_handle_test passes, Mtp works
with large folders

Change-Id: I8a980612c3eb941552ff4dd11ac631d1dc5d3347
parent 6b98328f
Loading
Loading
Loading
Loading
+34 −15
Original line number Original line Diff line number Diff line
@@ -127,27 +127,45 @@ void MtpFfsHandle::closeConfig() {
    mControl.reset();
    mControl.reset();
}
}


int MtpFfsHandle::doAsync(void* data, size_t len, bool read) {
int MtpFfsHandle::doAsync(void* data, size_t len, bool read, bool zero_packet) {
    struct io_event ioevs[1];
    struct io_event ioevs[AIO_BUFS_MAX];
    if (len > AIO_BUF_LEN) {
    size_t total = 0;
        LOG(ERROR) << "Mtp read/write too large " << len;

        errno = EINVAL;
    while (total < len) {
        return -1;
        size_t this_len = std::min(len - total, static_cast<size_t>(AIO_BUF_LEN * AIO_BUFS_MAX));
        int num_bufs = this_len / AIO_BUF_LEN + (this_len % AIO_BUF_LEN == 0 ? 0 : 1);
        for (int i = 0; i < num_bufs; i++) {
            mIobuf[0].buf[i] = reinterpret_cast<unsigned char*>(data) + total + i * AIO_BUF_LEN;
        }
        }
    mIobuf[0].buf[0] = reinterpret_cast<unsigned char*>(data);
        int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, this_len, read);
    if (iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, len, read) == -1)
        if (ret < 0) return -1;
        return -1;
        ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
    int ret = waitEvents(&mIobuf[0], 1, ioevs, nullptr);
        if (ret < 0) return -1;
    mIobuf[0].buf[0] = mIobuf[0].bufs.data();
        total += ret;
    return ret;
        if (static_cast<size_t>(ret) < this_len) break;
    }

    int packet_size = getPacketSize(read ? mBulkOut : mBulkIn);
    if (len % packet_size == 0 && zero_packet) {
        int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, 0, read);
        if (ret < 0) return -1;
        ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
        if (ret < 0) return -1;
    }

    for (unsigned i = 0; i < AIO_BUFS_MAX; i++) {
        mIobuf[0].buf[i] = mIobuf[0].bufs.data() + i * AIO_BUF_LEN;
    }
    return total;
}
}


int MtpFfsHandle::read(void* data, size_t len) {
int MtpFfsHandle::read(void* data, size_t len) {
    return doAsync(data, len, true);
    // Zero packets are handled by receiveFile()
    return doAsync(data, len, true, false);
}
}


int MtpFfsHandle::write(const void* data, size_t len) {
int MtpFfsHandle::write(const void* data, size_t len) {
    return doAsync(const_cast<void*>(data), len, false);
    return doAsync(const_cast<void*>(data), len, false, true);
}
}


int MtpFfsHandle::handleEvent() {
int MtpFfsHandle::handleEvent() {
@@ -570,7 +588,8 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) {
    if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
    if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
                    sizeof(mtp_data_header), init_read_len, offset))
                    sizeof(mtp_data_header), init_read_len, offset))
            != init_read_len) return -1;
            != init_read_len) return -1;
    if (write(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len) == -1)
    if (doAsync(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len,
                false, false /* zlps are handled below */) == -1)
        return -1;
        return -1;
    file_length -= init_read_len;
    file_length -= init_read_len;
    offset += init_read_len;
    offset += init_read_len;
+1 −1
Original line number Original line Diff line number Diff line
@@ -48,7 +48,7 @@ protected:
    void closeEndpoints();
    void closeEndpoints();
    void advise(int fd);
    void advise(int fd);
    int handleControlRequest(const struct usb_ctrlrequest *request);
    int handleControlRequest(const struct usb_ctrlrequest *request);
    int doAsync(void* data, size_t len, bool read);
    int doAsync(void* data, size_t len, bool read, bool zero_packet);
    int handleEvent();
    int handleEvent();
    void cancelTransaction();
    void cancelTransaction();
    void doSendEvent(mtp_event me);
    void doSendEvent(mtp_event me);
+30 −0
Original line number Original line Diff line number Diff line
@@ -123,6 +123,21 @@ TYPED_TEST(MtpFfsHandleTest, testRead) {
    EXPECT_STREQ(buf, dummyDataStr.c_str());
    EXPECT_STREQ(buf, dummyDataStr.c_str());
}
}


TYPED_TEST(MtpFfsHandleTest, testReadLarge) {
    std::stringstream ss;
    int size = TEST_PACKET_SIZE * MED_MULT;
    char buf[size + 1];
    buf[size] = '\0';

    for (int i = 0; i < MED_MULT; i++)
        ss << dummyDataStr;

    EXPECT_EQ(write(this->bulk_out, ss.str().c_str(), size), size);
    EXPECT_EQ(this->handle->read(buf, size), size);

    EXPECT_STREQ(buf, ss.str().c_str());
}

TYPED_TEST(MtpFfsHandleTest, testWrite) {
TYPED_TEST(MtpFfsHandleTest, testWrite) {
    char buf[TEST_PACKET_SIZE + 1];
    char buf[TEST_PACKET_SIZE + 1];
    buf[TEST_PACKET_SIZE] = '\0';
    buf[TEST_PACKET_SIZE] = '\0';
@@ -131,6 +146,21 @@ TYPED_TEST(MtpFfsHandleTest, testWrite) {
    EXPECT_STREQ(buf, dummyDataStr.c_str());
    EXPECT_STREQ(buf, dummyDataStr.c_str());
}
}


TYPED_TEST(MtpFfsHandleTest, testWriteLarge) {
    std::stringstream ss;
    int size = TEST_PACKET_SIZE * MED_MULT;
    char buf[size + 1];
    buf[size] = '\0';

    for (int i = 0; i < MED_MULT; i++)
        ss << dummyDataStr;

    EXPECT_EQ(this->handle->write(ss.str().c_str(), size), size);
    EXPECT_EQ(read(this->bulk_in, buf, size), size);

    EXPECT_STREQ(buf, ss.str().c_str());
}

TYPED_TEST(MtpFfsHandleTest, testReceiveFileEmpty) {
TYPED_TEST(MtpFfsHandleTest, testReceiveFileEmpty) {
    std::stringstream ss;
    std::stringstream ss;
    mtp_file_range mfr;
    mtp_file_range mfr;