blob: 01b6f2edbe3f1bb00953a5c62514dcf6e40d0560 [file] [log] [blame]
bigbiff bigbiffaf32bb92018-12-18 18:39:53 -05001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <android-base/logging.h>
18#include <android-base/properties.h>
19#include <asyncio/AsyncIO.h>
20#include <dirent.h>
21#include <errno.h>
22#include <fcntl.h>
23#include <memory>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/eventfd.h>
28#include <sys/ioctl.h>
29#include <sys/mman.h>
30#include <sys/poll.h>
31#include <sys/stat.h>
32#include <sys/types.h>
33#include <unistd.h>
34
35#include "PosixAsyncIO.h"
36#include "MtpDescriptors.h"
37#include "MtpFfsHandle.h"
38#include "mtp.h"
39#include "MtpDebug.h"
40
41namespace {
42
43constexpr unsigned AIO_BUFS_MAX = 128;
44constexpr unsigned AIO_BUF_LEN = 16384;
45
46constexpr unsigned FFS_NUM_EVENTS = 5;
47
48constexpr unsigned MAX_FILE_CHUNK_SIZE = AIO_BUFS_MAX * AIO_BUF_LEN;
49
50constexpr uint32_t MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
51
52struct timespec ZERO_TIMEOUT = { 0, 0 };
53
54struct mtp_device_status {
55 uint16_t wLength;
56 uint16_t wCode;
57};
58
59} // anonymous namespace
60
61int MtpFfsHandle::getPacketSize(int ffs_fd) {
62 struct usb_endpoint_descriptor desc;
63 if (ioctl(ffs_fd, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&desc))) {
64 MTPE("Could not get FFS bulk-in descriptor\n");
65 return MAX_PACKET_SIZE_HS;
66 } else {
67 return desc.wMaxPacketSize;
68 }
69}
70
71MtpFfsHandle::MtpFfsHandle(int controlFd) {
72 mControl.reset(controlFd);
73}
74
75MtpFfsHandle::~MtpFfsHandle() {}
76
77void MtpFfsHandle::closeEndpoints() {
78 mIntr.reset();
79 mBulkIn.reset();
80 mBulkOut.reset();
81}
82
83bool MtpFfsHandle::openEndpoints(bool ptp) {
84 if (mBulkIn < 0) {
85 mBulkIn.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_IN : FFS_MTP_EP_IN, O_RDWR)));
86 if (mBulkIn < 0) {
87 MTPE("cannot open bulk in ep\n");
88 return false;
89 }
90 }
91
92 if (mBulkOut < 0) {
93 mBulkOut.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_OUT : FFS_MTP_EP_OUT, O_RDWR)));
94 if (mBulkOut < 0) {
95 MTPE("cannot open bulk out ep\n");
96 return false;
97 }
98 }
99
100 if (mIntr < 0) {
101 mIntr.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_INTR : FFS_MTP_EP_INTR, O_RDWR)));
102 if (mIntr < 0) {
103 MTPE("cannot open intr ep\n");
104 return false;
105 }
106 }
107 return true;
108}
109
110void MtpFfsHandle::advise(int fd) {
111 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
112 if (posix_madvise(mIobuf[i].bufs.data(), MAX_FILE_CHUNK_SIZE,
113 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED) < 0)
114 MTPE("Failed to madvise\n");
115 }
116 if (posix_fadvise(fd, 0, 0,
117 POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED) < 0)
118 MTPE("Failed to fadvise\n");
119}
120
121bool MtpFfsHandle::writeDescriptors(bool ptp) {
122 return ::writeDescriptors(mControl, ptp);
123}
124
125void MtpFfsHandle::closeConfig() {
126 mControl.reset();
127}
128
129int MtpFfsHandle::doAsync(void* data, size_t len, bool read, bool zero_packet) {
130 struct io_event ioevs[AIO_BUFS_MAX];
131 size_t total = 0;
132
133 while (total < len) {
134 size_t this_len = std::min(len - total, static_cast<size_t>(AIO_BUF_LEN * AIO_BUFS_MAX));
135 int num_bufs = this_len / AIO_BUF_LEN + (this_len % AIO_BUF_LEN == 0 ? 0 : 1);
136 for (int i = 0; i < num_bufs; i++) {
137 mIobuf[0].buf[i] = reinterpret_cast<unsigned char*>(data) + total + i * AIO_BUF_LEN;
138 }
139 int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, this_len, read);
140 if (ret < 0) return -1;
141 ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
142 if (ret < 0) return -1;
143 total += ret;
144 if (static_cast<size_t>(ret) < this_len) break;
145 }
146
147 int packet_size = getPacketSize(read ? mBulkOut : mBulkIn);
148 if (len % packet_size == 0 && zero_packet) {
149 int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, 0, read);
150 if (ret < 0) return -1;
151 ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
152 if (ret < 0) return -1;
153 }
154
155 for (unsigned i = 0; i < AIO_BUFS_MAX; i++) {
156 mIobuf[0].buf[i] = mIobuf[0].bufs.data() + i * AIO_BUF_LEN;
157 }
158 return total;
159}
160
161int MtpFfsHandle::read(void* data, size_t len) {
162 // Zero packets are handled by receiveFile()
163 return doAsync(data, len, true, false);
164}
165
166int MtpFfsHandle::write(const void* data, size_t len) {
167 return doAsync(const_cast<void*>(data), len, false, true);
168}
169
170int MtpFfsHandle::handleEvent() {
171
172 std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
173 usb_functionfs_event *event = events.data();
174 int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
175 events.size() * sizeof(usb_functionfs_event)));
176 if (nbytes == -1) {
177 return -1;
178 }
179 int ret = 0;
180 for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
181 switch (event->type) {
182 case FUNCTIONFS_BIND:
183 case FUNCTIONFS_ENABLE:
184 ret = 0;
185 errno = 0;
186 break;
187 case FUNCTIONFS_UNBIND:
188 case FUNCTIONFS_DISABLE:
189 errno = ESHUTDOWN;
190 ret = -1;
191 break;
192 case FUNCTIONFS_SETUP:
193 if (handleControlRequest(&event->u.setup) == -1)
194 ret = -1;
195 break;
196 case FUNCTIONFS_SUSPEND:
197 case FUNCTIONFS_RESUME:
198 break;
199 default:
200 MTPE("Mtp Event (unknown)\n");
201 }
202 }
203 return ret;
204}
205
206int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
207 uint8_t type = setup->bRequestType;
208 uint8_t code = setup->bRequest;
209 uint16_t length = setup->wLength;
210 uint16_t index = setup->wIndex;
211 uint16_t value = setup->wValue;
212 std::vector<char> buf;
213 buf.resize(length);
214 int ret = 0;
215
216 if (!(type & USB_DIR_IN)) {
217 if (::read(mControl, buf.data(), length) != length) {
218 MTPE("Mtp error ctrlreq read data");
219 }
220 }
221
222 if ((type & USB_TYPE_MASK) == USB_TYPE_CLASS && index == 0 && value == 0) {
223 switch(code) {
224 case MTP_REQ_RESET:
225 case MTP_REQ_CANCEL:
226 errno = ECANCELED;
227 ret = -1;
228 break;
229 case MTP_REQ_GET_DEVICE_STATUS:
230 {
231 if (length < sizeof(struct mtp_device_status) + 4) {
232 errno = EINVAL;
233 return -1;
234 }
235 struct mtp_device_status *st = reinterpret_cast<struct mtp_device_status*>(buf.data());
236 st->wLength = htole16(sizeof(st));
237 if (mCanceled) {
238 st->wLength += 4;
239 st->wCode = MTP_RESPONSE_TRANSACTION_CANCELLED;
240 uint16_t *endpoints = reinterpret_cast<uint16_t*>(st + 1);
241 endpoints[0] = ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_REVMAP);
242 endpoints[1] = ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_REVMAP);
243 mCanceled = false;
244 } else {
245 st->wCode = MTP_RESPONSE_OK;
246 }
247 length = st->wLength;
248 break;
249 }
250 default:
251 MTPE("Unrecognized Mtp class request!\n");
252 }
253 } else {
254 MTPE("Unrecognized request type\n");
255 }
256
257 if (type & USB_DIR_IN) {
258 if (::write(mControl, buf.data(), length) != length) {
259 MTPE("Mtp error ctrlreq write data");
260 }
261 }
262 return 0;
263}
264
265int MtpFfsHandle::start(bool ptp) {
266 if (!openEndpoints(ptp))
267 return -1;
268
269 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
270 mIobuf[i].bufs.resize(MAX_FILE_CHUNK_SIZE);
271 mIobuf[i].iocb.resize(AIO_BUFS_MAX);
272 mIobuf[i].iocbs.resize(AIO_BUFS_MAX);
273 mIobuf[i].buf.resize(AIO_BUFS_MAX);
274 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
275 mIobuf[i].buf[j] = mIobuf[i].bufs.data() + j * AIO_BUF_LEN;
276 mIobuf[i].iocb[j] = &mIobuf[i].iocbs[j];
277 }
278 }
279
280 memset(&mCtx, 0, sizeof(mCtx));
281 if (io_setup(AIO_BUFS_MAX, &mCtx) < 0) {
282 MTPE("unable to setup aio");
283 return -1;
284 }
285 mEventFd.reset(eventfd(0, EFD_NONBLOCK));
286 mPollFds[0].fd = mControl;
287 mPollFds[0].events = POLLIN;
288 mPollFds[1].fd = mEventFd;
289 mPollFds[1].events = POLLIN;
290
291 mCanceled = false;
292 return 0;
293}
294
295void MtpFfsHandle::close() {
296 io_destroy(mCtx);
297 closeEndpoints();
298 closeConfig();
299}
300
301int MtpFfsHandle::waitEvents(__attribute__((unused)) struct io_buffer *buf, int min_events, struct io_event *events,
302 int *counter) {
303 int num_events = 0;
304 int ret = 0;
305 int error = 0;
306
307 while (num_events < min_events) {
308 if (poll(mPollFds, 2, 0) == -1) {
309 MTPE("Mtp error during poll()\n");
310 return -1;
311 }
312 if (mPollFds[0].revents & POLLIN) {
313 mPollFds[0].revents = 0;
314 if (handleEvent() == -1) {
315 error = errno;
316 }
317 }
318 if (mPollFds[1].revents & POLLIN) {
319 mPollFds[1].revents = 0;
320 uint64_t ev_cnt = 0;
321
322 if (::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1) {
323 MTPE("Mtp unable to read eventfd\n");
324 error = errno;
325 continue;
326 }
327
328 // It's possible that io_getevents will return more events than the eventFd reported,
329 // since events may appear in the time between the calls. In this case, the eventFd will
330 // show up as readable next iteration, but there will be fewer or no events to actually
331 // wait for. Thus we never want io_getevents to block.
332 int this_events = TEMP_FAILURE_RETRY(io_getevents(mCtx, 0, AIO_BUFS_MAX, events, &ZERO_TIMEOUT));
333 if (this_events == -1) {
334 MTPE("Mtp error getting events");
335 error = errno;
336 }
337 // Add up the total amount of data and find errors on the way.
338 for (unsigned j = 0; j < static_cast<unsigned>(this_events); j++) {
339 if (events[j].res < 0) {
340 errno = -events[j].res;
341 MTPE("Mtp got error event\n");
342 error = errno;
343 }
344 ret += events[j].res;
345 }
346 num_events += this_events;
347 if (counter)
348 *counter += this_events;
349 }
350 if (error) {
351 errno = error;
352 ret = -1;
353 break;
354 }
355 }
356 return ret;
357}
358
359void MtpFfsHandle::cancelTransaction() {
360 // Device cancels by stalling both bulk endpoints.
361 if (::read(mBulkIn, nullptr, 0) != -1 || errno != EBADMSG)
362 MTPE("Mtp stall failed on bulk in\n");
363 if (::write(mBulkOut, nullptr, 0) != -1 || errno != EBADMSG)
364 MTPE("Mtp stall failed on bulk out\n");
365 mCanceled = true;
366 errno = ECANCELED;
367}
368
369int MtpFfsHandle::cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start,
370 unsigned end) {
371 // Some manpages for io_cancel are out of date and incorrect.
372 // io_cancel will return -EINPROGRESS on success and does
373 // not place the event in the given memory. We have to use
374 // io_getevents to wait for all the events we cancelled.
375 int ret = 0;
376 unsigned num_events = 0;
377 int save_errno = errno;
378 errno = 0;
379
380 for (unsigned j = start; j < end; j++) {
381 if (io_cancel(mCtx, iocb[j], nullptr) != -1 || errno != EINPROGRESS) {
382 MTPE("Mtp couldn't cancel request\n");
383 } else {
384 num_events++;
385 }
386 }
387 if (num_events != end - start) {
388 ret = -1;
389 errno = EIO;
390 }
391 int evs = TEMP_FAILURE_RETRY(io_getevents(mCtx, num_events, AIO_BUFS_MAX, events, nullptr));
392 if (static_cast<unsigned>(evs) != num_events) {
393 MTPE("Mtp couldn't cancel all requests\n");
394 ret = -1;
395 }
396
397 uint64_t ev_cnt = 0;
398 if (num_events && ::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1)
399 MTPE("Mtp Unable to read event fd\n");
400
401 if (ret == 0) {
402 // Restore errno since it probably got overriden with EINPROGRESS.
403 errno = save_errno;
404 }
405 return ret;
406}
407
408int MtpFfsHandle::iobufSubmit(struct io_buffer *buf, int fd, unsigned length, bool read) {
409 int ret = 0;
410 buf->actual = AIO_BUFS_MAX;
411 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
412 unsigned rq_length = std::min(AIO_BUF_LEN, length - AIO_BUF_LEN * j);
413 io_prep(buf->iocb[j], fd, buf->buf[j], rq_length, 0, read);
414 buf->iocb[j]->aio_flags |= IOCB_FLAG_RESFD;
415 buf->iocb[j]->aio_resfd = mEventFd;
416
417 // Not enough data, so table is truncated.
418 if (rq_length < AIO_BUF_LEN || length == AIO_BUF_LEN * (j + 1)) {
419 buf->actual = j + 1;
420 break;
421 }
422 }
423
424 ret = io_submit(mCtx, buf->actual, buf->iocb.data());
425 if (ret != static_cast<int>(buf->actual)) {
426 MTPE("Mtp io_submit\n");
427 if (ret != -1) {
428 errno = EIO;
429 }
430 ret = -1;
431 }
432 return ret;
433}
434
435int MtpFfsHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
436 // When receiving files, the incoming length is given in 32 bits.
437 // A >=4G file is given as 0xFFFFFFFF
438 uint32_t file_length = mfr.length;
439 uint64_t offset = mfr.offset;
440
441 struct aiocb aio;
442 aio.aio_fildes = mfr.fd;
443 aio.aio_buf = nullptr;
444 struct aiocb *aiol[] = {&aio};
445
446 int ret = -1;
447 unsigned i = 0;
448 size_t length;
449 struct io_event ioevs[AIO_BUFS_MAX];
450 bool has_write = false;
451 bool error = false;
452 bool write_error = false;
453 int packet_size = getPacketSize(mBulkOut);
454 bool short_packet = false;
455 advise(mfr.fd);
456
457 // Break down the file into pieces that fit in buffers
458 while (file_length > 0 || has_write) {
459 // Queue an asynchronous read from USB.
460 if (file_length > 0) {
461 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
462 if (iobufSubmit(&mIobuf[i], mBulkOut, length, true) == -1)
463 error = true;
464 }
465
466 // Get the return status of the last write request.
467 if (has_write) {
468 aio_suspend(aiol, 1, nullptr);
469 int written = aio_return(&aio);
470 if (static_cast<size_t>(written) < aio.aio_nbytes) {
471 errno = written == -1 ? aio_error(&aio) : EIO;
472 MTPE("Mtp error writing to disk\n");
473 write_error = true;
474 }
475 has_write = false;
476 }
477
478 if (error) {
479 return -1;
480 }
481
482 // Get the result of the read request, and queue a write to disk.
483 if (file_length > 0) {
484 unsigned num_events = 0;
485 ret = 0;
486 unsigned short_i = mIobuf[i].actual;
487 while (num_events < short_i) {
488 // Get all events up to the short read, if there is one.
489 // We must wait for each event since data transfer could end at any time.
490 int this_events = 0;
491 int event_ret = waitEvents(&mIobuf[i], 1, ioevs, &this_events);
492 num_events += this_events;
493
494 if (event_ret == -1) {
495 cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual);
496 return -1;
497 }
498 ret += event_ret;
499 for (int j = 0; j < this_events; j++) {
500 // struct io_event contains a pointer to the associated struct iocb as a __u64.
501 if (static_cast<__u64>(ioevs[j].res) <
502 reinterpret_cast<struct iocb*>(ioevs[j].obj)->aio_nbytes) {
503 // We've found a short event. Store the index since
504 // events won't necessarily arrive in the order they are queued.
505 short_i = (ioevs[j].obj - reinterpret_cast<uint64_t>(mIobuf[i].iocbs.data()))
506 / sizeof(struct iocb) + 1;
507 short_packet = true;
508 }
509 }
510 }
511 if (short_packet) {
512 if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual)) {
513 write_error = true;
514 }
515 }
516 if (file_length == MAX_MTP_FILE_SIZE) {
517 // For larger files, receive until a short packet is received.
518 if (static_cast<size_t>(ret) < length) {
519 file_length = 0;
520 }
521 } else if (ret < static_cast<int>(length)) {
522 // If file is less than 4G and we get a short packet, it's an error.
523 errno = EIO;
524 MTPE("Mtp got unexpected short packet\n");
525 return -1;
526 } else {
527 file_length -= ret;
528 }
529
530 if (write_error) {
531 cancelTransaction();
532 return -1;
533 }
534
535 // Enqueue a new write request
536 aio_prepare(&aio, mIobuf[i].bufs.data(), ret, offset);
537 aio_write(&aio);
538
539 offset += ret;
540 i = (i + 1) % NUM_IO_BUFS;
541 has_write = true;
542 }
543 }
544 if ((ret % packet_size == 0 && !short_packet) || zero_packet) {
545 // Receive an empty packet if size is a multiple of the endpoint size
546 // and we didn't already get an empty packet from the header or large file.
547 if (read(mIobuf[0].bufs.data(), packet_size) != 0) {
548 return -1;
549 }
550 }
551 return 0;
552}
553
554int MtpFfsHandle::sendFile(mtp_file_range mfr) {
555 uint64_t file_length = mfr.length;
556 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
557 file_length + sizeof(mtp_data_header));
558 uint64_t offset = mfr.offset;
559 int packet_size = getPacketSize(mBulkIn);
560
561 // If file_length is larger than a size_t, truncating would produce the wrong comparison.
562 // Instead, promote the left side to 64 bits, then truncate the small result.
563 int init_read_len = std::min(
564 static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
565
566 advise(mfr.fd);
567
568 struct aiocb aio;
569 aio.aio_fildes = mfr.fd;
570 struct aiocb *aiol[] = {&aio};
571 int ret = 0;
572 int length, num_read;
573 unsigned i = 0;
574 struct io_event ioevs[AIO_BUFS_MAX];
575 bool error = false;
576 bool has_write = false;
577
578 // Send the header data
579 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(mIobuf[0].bufs.data());
580 header->length = htole32(given_length);
581 header->type = htole16(2); // data packet
582 header->command = htole16(mfr.command);
583 header->transaction_id = htole32(mfr.transaction_id);
584
585 // Some hosts don't support header/data separation even though MTP allows it
586 // Handle by filling first packet with initial file data
587 if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
588 sizeof(mtp_data_header), init_read_len, offset))
589 != init_read_len) return -1;
590 if (doAsync(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len,
591 false, false /* zlps are handled below */) == -1)
592 return -1;
593 file_length -= init_read_len;
594 offset += init_read_len;
595 ret = init_read_len + sizeof(mtp_data_header);
596
597 // Break down the file into pieces that fit in buffers
598 while(file_length > 0 || has_write) {
599 if (file_length > 0) {
600 // Queue up a read from disk.
601 length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
602 aio_prepare(&aio, mIobuf[i].bufs.data(), length, offset);
603 aio_read(&aio);
604 }
605
606 if (has_write) {
607 // Wait for usb write. Cancel unwritten portion if there's an error.
608 int num_events = 0;
609 if (waitEvents(&mIobuf[(i-1)%NUM_IO_BUFS], mIobuf[(i-1)%NUM_IO_BUFS].actual, ioevs,
610 &num_events) != ret) {
611 error = true;
612 cancelEvents(mIobuf[(i-1)%NUM_IO_BUFS].iocb.data(), ioevs, num_events,
613 mIobuf[(i-1)%NUM_IO_BUFS].actual);
614 }
615 has_write = false;
616 }
617
618 if (file_length > 0) {
619 // Wait for the previous read to finish
620 aio_suspend(aiol, 1, nullptr);
621 num_read = aio_return(&aio);
622 if (static_cast<size_t>(num_read) < aio.aio_nbytes) {
623 errno = num_read == -1 ? aio_error(&aio) : EIO;
624 MTPE("Mtp error reading from disk\n");
625 cancelTransaction();
626 return -1;
627 }
628
629 file_length -= num_read;
630 offset += num_read;
631
632 if (error) {
633 return -1;
634 }
635
636 // Queue up a write to usb.
637 if (iobufSubmit(&mIobuf[i], mBulkIn, num_read, false) == -1) {
638 return -1;
639 }
640 has_write = true;
641 ret = num_read;
642 }
643
644 i = (i + 1) % NUM_IO_BUFS;
645 }
646
647 if (ret % packet_size == 0) {
648 // If the last packet wasn't short, send a final empty packet
649 if (write(mIobuf[0].bufs.data(), 0) != 0) {
650 return -1;
651 }
652 }
653 return 0;
654}
655
656int MtpFfsHandle::sendEvent(mtp_event me) {
657 // Mimic the behavior of f_mtp by sending the event async.
658 // Events aren't critical to the connection, so we don't need to check the return value.
659 char *temp = new char[me.length];
660 memcpy(temp, me.data, me.length);
661 me.data = temp;
662 std::thread t([this, me]() { return this->doSendEvent(me); });
663 t.detach();
664 return 0;
665}
666
667void MtpFfsHandle::doSendEvent(mtp_event me) {
668 unsigned length = me.length;
669 int ret = ::write(mIntr, me.data, length);
670 if (static_cast<unsigned>(ret) != length)
671 MTPE("Mtp error sending event thread!\n");
672 delete[] reinterpret_cast<char*>(me.data);
673}
674