Loading media/mtp/MtpFfsHandle.cpp +34 −15 Original line number Diff line number Diff line Loading @@ -127,27 +127,45 @@ void MtpFfsHandle::closeConfig() { mControl.reset(); } int MtpFfsHandle::doAsync(void* data, size_t len, bool read) { struct io_event ioevs[1]; if (len > AIO_BUF_LEN) { LOG(ERROR) << "Mtp read/write too large " << len; errno = EINVAL; return -1; int MtpFfsHandle::doAsync(void* data, size_t len, bool read, bool zero_packet) { struct io_event ioevs[AIO_BUFS_MAX]; size_t total = 0; while (total < len) { 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); if (iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, len, read) == -1) return -1; int ret = waitEvents(&mIobuf[0], 1, ioevs, nullptr); mIobuf[0].buf[0] = mIobuf[0].bufs.data(); return ret; int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, this_len, read); if (ret < 0) return -1; ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr); if (ret < 0) return -1; total += 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) { 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) { return doAsync(const_cast<void*>(data), len, false); return doAsync(const_cast<void*>(data), len, false, true); } int MtpFfsHandle::handleEvent() { Loading Loading @@ -570,7 +588,8 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) { if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() + sizeof(mtp_data_header), init_read_len, offset)) != 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; file_length -= init_read_len; offset += init_read_len; Loading media/mtp/MtpFfsHandle.h +1 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ protected: void closeEndpoints(); void advise(int fd); 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(); void cancelTransaction(); void doSendEvent(mtp_event me); Loading media/mtp/tests/MtpFfsHandle_test.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,21 @@ TYPED_TEST(MtpFfsHandleTest, testRead) { 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) { char buf[TEST_PACKET_SIZE + 1]; buf[TEST_PACKET_SIZE] = '\0'; Loading @@ -131,6 +146,21 @@ TYPED_TEST(MtpFfsHandleTest, testWrite) { 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) { std::stringstream ss; mtp_file_range mfr; Loading Loading
media/mtp/MtpFfsHandle.cpp +34 −15 Original line number Diff line number Diff line Loading @@ -127,27 +127,45 @@ void MtpFfsHandle::closeConfig() { mControl.reset(); } int MtpFfsHandle::doAsync(void* data, size_t len, bool read) { struct io_event ioevs[1]; if (len > AIO_BUF_LEN) { LOG(ERROR) << "Mtp read/write too large " << len; errno = EINVAL; return -1; int MtpFfsHandle::doAsync(void* data, size_t len, bool read, bool zero_packet) { struct io_event ioevs[AIO_BUFS_MAX]; size_t total = 0; while (total < len) { 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); if (iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, len, read) == -1) return -1; int ret = waitEvents(&mIobuf[0], 1, ioevs, nullptr); mIobuf[0].buf[0] = mIobuf[0].bufs.data(); return ret; int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, this_len, read); if (ret < 0) return -1; ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr); if (ret < 0) return -1; total += 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) { 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) { return doAsync(const_cast<void*>(data), len, false); return doAsync(const_cast<void*>(data), len, false, true); } int MtpFfsHandle::handleEvent() { Loading Loading @@ -570,7 +588,8 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) { if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() + sizeof(mtp_data_header), init_read_len, offset)) != 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; file_length -= init_read_len; offset += init_read_len; Loading
media/mtp/MtpFfsHandle.h +1 −1 Original line number Diff line number Diff line Loading @@ -48,7 +48,7 @@ protected: void closeEndpoints(); void advise(int fd); 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(); void cancelTransaction(); void doSendEvent(mtp_event me); Loading
media/mtp/tests/MtpFfsHandle_test.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -123,6 +123,21 @@ TYPED_TEST(MtpFfsHandleTest, testRead) { 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) { char buf[TEST_PACKET_SIZE + 1]; buf[TEST_PACKET_SIZE] = '\0'; Loading @@ -131,6 +146,21 @@ TYPED_TEST(MtpFfsHandleTest, testWrite) { 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) { std::stringstream ss; mtp_file_range mfr; Loading