blob: ad3c06881dbc96d70bf91c95f7ca0668ecfc21ca [file] [log] [blame]
Jerry Zhang487be612016-10-24 12:10:41 -07001/*
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>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070019#include <asyncio/AsyncIO.h>
Jerry Zhang487be612016-10-24 12:10:41 -070020#include <dirent.h>
21#include <errno.h>
22#include <fcntl.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070023#include <memory>
Jerry Zhang487be612016-10-24 12:10:41 -070024#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070027#include <sys/eventfd.h>
Jerry Zhang487be612016-10-24 12:10:41 -070028#include <sys/ioctl.h>
Jerry Zhange9d94422017-01-18 12:03:56 -080029#include <sys/mman.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070030#include <sys/poll.h>
Jerry Zhang487be612016-10-24 12:10:41 -070031#include <sys/stat.h>
32#include <sys/types.h>
33#include <unistd.h>
Jerry Zhang487be612016-10-24 12:10:41 -070034
Jerry Zhangdf69dd32017-05-03 17:17:49 -070035#include "PosixAsyncIO.h"
Jerry Zhang69b74502017-10-02 16:26:37 -070036#include "MtpDescriptors.h"
Jerry Zhang487be612016-10-24 12:10:41 -070037#include "MtpFfsHandle.h"
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -080038#include "mtp.h"
Jerry Zhang487be612016-10-24 12:10:41 -070039
Jerry Zhang487be612016-10-24 12:10:41 -070040namespace {
41
Jerry Zhangdf69dd32017-05-03 17:17:49 -070042constexpr unsigned AIO_BUFS_MAX = 128;
43constexpr unsigned AIO_BUF_LEN = 16384;
Jerry Zhang487be612016-10-24 12:10:41 -070044
Jerry Zhangdf69dd32017-05-03 17:17:49 -070045constexpr unsigned FFS_NUM_EVENTS = 5;
Jerry Zhang487be612016-10-24 12:10:41 -070046
Jerry Zhangdf69dd32017-05-03 17:17:49 -070047constexpr unsigned MAX_FILE_CHUNK_SIZE = AIO_BUFS_MAX * AIO_BUF_LEN;
Jerry Zhangb4f54262017-02-02 18:14:33 -080048
Jerry Zhangdf69dd32017-05-03 17:17:49 -070049constexpr uint32_t MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
Jerry Zhang487be612016-10-24 12:10:41 -070050
Jerry Zhangdf69dd32017-05-03 17:17:49 -070051struct timespec ZERO_TIMEOUT = { 0, 0 };
Jerry Zhangb4f54262017-02-02 18:14:33 -080052
Jerry Zhangdf69dd32017-05-03 17:17:49 -070053struct mtp_device_status {
54 uint16_t wLength;
55 uint16_t wCode;
56};
57
Jerry Zhang487be612016-10-24 12:10:41 -070058} // anonymous namespace
59
60namespace android {
61
Jerry Zhangdf69dd32017-05-03 17:17:49 -070062int MtpFfsHandle::getPacketSize(int ffs_fd) {
63 struct usb_endpoint_descriptor desc;
64 if (ioctl(ffs_fd, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&desc))) {
65 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
66 return MAX_PACKET_SIZE_HS;
67 } else {
68 return desc.wMaxPacketSize;
69 }
70}
71
Jerry Zhang63dac452017-12-06 15:19:36 -080072MtpFfsHandle::MtpFfsHandle(int controlFd) {
73 mControl.reset(controlFd);
74}
Jerry Zhang487be612016-10-24 12:10:41 -070075
76MtpFfsHandle::~MtpFfsHandle() {}
77
78void MtpFfsHandle::closeEndpoints() {
79 mIntr.reset();
80 mBulkIn.reset();
81 mBulkOut.reset();
82}
83
Jerry Zhang63dac452017-12-06 15:19:36 -080084bool MtpFfsHandle::openEndpoints(bool ptp) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -070085 if (mBulkIn < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -080086 mBulkIn.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_IN : FFS_MTP_EP_IN, O_RDWR)));
Jerry Zhangdf69dd32017-05-03 17:17:49 -070087 if (mBulkIn < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -080088 PLOG(ERROR) << (ptp ? FFS_PTP_EP_IN : FFS_MTP_EP_IN) << ": cannot open bulk in ep";
Jerry Zhangdf69dd32017-05-03 17:17:49 -070089 return false;
90 }
91 }
92
93 if (mBulkOut < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -080094 mBulkOut.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_OUT : FFS_MTP_EP_OUT, O_RDWR)));
Jerry Zhangdf69dd32017-05-03 17:17:49 -070095 if (mBulkOut < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -080096 PLOG(ERROR) << (ptp ? FFS_PTP_EP_OUT : FFS_MTP_EP_OUT) << ": cannot open bulk out ep";
Jerry Zhangdf69dd32017-05-03 17:17:49 -070097 return false;
98 }
99 }
100
101 if (mIntr < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -0800102 mIntr.reset(TEMP_FAILURE_RETRY(open(ptp ? FFS_PTP_EP_INTR : FFS_MTP_EP_INTR, O_RDWR)));
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700103 if (mIntr < 0) {
Jerry Zhang63dac452017-12-06 15:19:36 -0800104 PLOG(ERROR) << (ptp ? FFS_PTP_EP_INTR : FFS_MTP_EP_INTR) << ": cannot open intr ep";
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700105 return false;
106 }
107 }
108 return true;
109}
110
111void MtpFfsHandle::advise(int fd) {
112 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
113 if (posix_madvise(mIobuf[i].bufs.data(), MAX_FILE_CHUNK_SIZE,
114 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED) < 0)
115 PLOG(ERROR) << "Failed to madvise";
116 }
117 if (posix_fadvise(fd, 0, 0,
118 POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED) < 0)
119 PLOG(ERROR) << "Failed to fadvise";
120}
121
Jerry Zhang63dac452017-12-06 15:19:36 -0800122bool MtpFfsHandle::writeDescriptors(bool ptp) {
123 return ::android::writeDescriptors(mControl, ptp);
Jerry Zhang487be612016-10-24 12:10:41 -0700124}
125
126void MtpFfsHandle::closeConfig() {
127 mControl.reset();
128}
129
Jerry Zhang297912b2018-05-11 11:29:54 -0700130int MtpFfsHandle::doAsync(void* data, size_t len, bool read, bool zero_packet) {
131 struct io_event ioevs[AIO_BUFS_MAX];
132 size_t total = 0;
133
134 while (total < len) {
135 size_t this_len = std::min(len - total, static_cast<size_t>(AIO_BUF_LEN * AIO_BUFS_MAX));
136 int num_bufs = this_len / AIO_BUF_LEN + (this_len % AIO_BUF_LEN == 0 ? 0 : 1);
137 for (int i = 0; i < num_bufs; i++) {
138 mIobuf[0].buf[i] = reinterpret_cast<unsigned char*>(data) + total + i * AIO_BUF_LEN;
139 }
140 int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, this_len, read);
141 if (ret < 0) return -1;
142 ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
143 if (ret < 0) return -1;
144 total += ret;
145 if (static_cast<size_t>(ret) < this_len) break;
Jerry Zhang487be612016-10-24 12:10:41 -0700146 }
Jerry Zhang297912b2018-05-11 11:29:54 -0700147
148 int packet_size = getPacketSize(read ? mBulkOut : mBulkIn);
149 if (len % packet_size == 0 && zero_packet) {
150 int ret = iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, 0, read);
151 if (ret < 0) return -1;
152 ret = waitEvents(&mIobuf[0], ret, ioevs, nullptr);
153 if (ret < 0) return -1;
154 }
155
156 for (unsigned i = 0; i < AIO_BUFS_MAX; i++) {
157 mIobuf[0].buf[i] = mIobuf[0].bufs.data() + i * AIO_BUF_LEN;
158 }
159 return total;
Jerry Zhang487be612016-10-24 12:10:41 -0700160}
161
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700162int MtpFfsHandle::read(void* data, size_t len) {
Jerry Zhang297912b2018-05-11 11:29:54 -0700163 // Zero packets are handled by receiveFile()
164 return doAsync(data, len, true, false);
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700165}
166
167int MtpFfsHandle::write(const void* data, size_t len) {
Jerry Zhang297912b2018-05-11 11:29:54 -0700168 return doAsync(const_cast<void*>(data), len, false, true);
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700169}
170
171int MtpFfsHandle::handleEvent() {
172
173 std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
174 usb_functionfs_event *event = events.data();
175 int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
176 events.size() * sizeof(usb_functionfs_event)));
177 if (nbytes == -1) {
178 return -1;
179 }
Jerry Zhang487be612016-10-24 12:10:41 -0700180 int ret = 0;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700181 for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
182 switch (event->type) {
183 case FUNCTIONFS_BIND:
184 case FUNCTIONFS_ENABLE:
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700185 ret = 0;
186 errno = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700187 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700188 case FUNCTIONFS_UNBIND:
189 case FUNCTIONFS_DISABLE:
190 errno = ESHUTDOWN;
191 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700192 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700193 case FUNCTIONFS_SETUP:
194 if (handleControlRequest(&event->u.setup) == -1)
195 ret = -1;
196 break;
Jerry Zhang63dac452017-12-06 15:19:36 -0800197 case FUNCTIONFS_SUSPEND:
198 case FUNCTIONFS_RESUME:
199 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700200 default:
201 LOG(ERROR) << "Mtp Event " << event->type << " (unknown)";
202 }
Jerry Zhang487be612016-10-24 12:10:41 -0700203 }
204 return ret;
205}
206
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700207int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
208 uint8_t type = setup->bRequestType;
209 uint8_t code = setup->bRequest;
210 uint16_t length = setup->wLength;
211 uint16_t index = setup->wIndex;
212 uint16_t value = setup->wValue;
213 std::vector<char> buf;
214 buf.resize(length);
Jerry Zhang487be612016-10-24 12:10:41 -0700215
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700216 if (!(type & USB_DIR_IN)) {
217 if (::read(mControl, buf.data(), length) != length) {
218 PLOG(ERROR) << "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;
James Weid97d79c2018-09-25 23:24:27 +0800227 return -1;
228 // break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700229 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 LOG(ERROR) << "Unrecognized Mtp class request! " << code;
252 }
253 } else {
254 LOG(ERROR) << "Unrecognized request type " << type;
255 }
256
257 if (type & USB_DIR_IN) {
258 if (::write(mControl, buf.data(), length) != length) {
259 PLOG(ERROR) << "Mtp error ctrlreq write data";
260 }
261 }
262 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700263}
264
Jerry Zhang63dac452017-12-06 15:19:36 -0800265int MtpFfsHandle::start(bool ptp) {
266 if (!openEndpoints(ptp))
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800267 return -1;
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800268
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700269 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];
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800277 }
278 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700279
280 memset(&mCtx, 0, sizeof(mCtx));
281 if (io_setup(AIO_BUFS_MAX, &mCtx) < 0) {
282 PLOG(ERROR) << "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;
Jerry Zhangb4f54262017-02-02 18:14:33 -0800292 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700293}
294
Jerry Zhang487be612016-10-24 12:10:41 -0700295void MtpFfsHandle::close() {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700296 io_destroy(mCtx);
Jerry Zhang487be612016-10-24 12:10:41 -0700297 closeEndpoints();
Jerry Zhang63dac452017-12-06 15:19:36 -0800298 closeConfig();
Jerry Zhang487be612016-10-24 12:10:41 -0700299}
300
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700301int MtpFfsHandle::waitEvents(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;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700306
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700307 while (num_events < min_events) {
308 if (poll(mPollFds, 2, 0) == -1) {
309 PLOG(ERROR) << "Mtp error during poll()";
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 PLOG(ERROR) << "Mtp unable to read eventfd";
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 PLOG(ERROR) << "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 PLOG(ERROR) << "Mtp got error event at " << j << " and " << buf->actual << " total";
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 PLOG(ERROR) << "Mtp stall failed on bulk in";
363 if (::write(mBulkOut, nullptr, 0) != -1 || errno != EBADMSG)
364 PLOG(ERROR) << "Mtp stall failed on bulk out";
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 PLOG(ERROR) << "Mtp couldn't cancel request " << j;
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 PLOG(ERROR) << "Mtp couldn't cancel all requests, got " << evs;
394 ret = -1;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700395 }
Jerry Zhang487be612016-10-24 12:10:41 -0700396
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700397 uint64_t ev_cnt = 0;
398 if (num_events && ::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1)
399 PLOG(ERROR) << "Mtp Unable to read event fd";
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 PLOG(ERROR) << "Mtp io_submit got " << ret << " expected " << buf->actual;
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;
Jerry Zhang487be612016-10-24 12:10:41 -0700440
441 struct aiocb aio;
442 aio.aio_fildes = mfr.fd;
443 aio.aio_buf = nullptr;
444 struct aiocb *aiol[] = {&aio};
Jerry Zhang487be612016-10-24 12:10:41 -0700445
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700446 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);
Jerry Zhang487be612016-10-24 12:10:41 -0700456
457 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700458 while (file_length > 0 || has_write) {
459 // Queue an asynchronous read from USB.
Jerry Zhang487be612016-10-24 12:10:41 -0700460 if (file_length > 0) {
461 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700462 if (iobufSubmit(&mIobuf[i], mBulkOut, length, true) == -1)
463 error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700464 }
465
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700466 // Get the return status of the last write request.
467 if (has_write) {
Jerry Zhang487be612016-10-24 12:10:41 -0700468 aio_suspend(aiol, 1, nullptr);
Jerry Zhang487be612016-10-24 12:10:41 -0700469 int written = aio_return(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700470 if (static_cast<size_t>(written) < aio.aio_nbytes) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700471 errno = written == -1 ? aio_error(&aio) : EIO;
472 PLOG(ERROR) << "Mtp error writing to disk";
473 write_error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700474 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700475 has_write = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700476 }
477
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700478 if (error) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700479 return -1;
480 }
481
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700482 // 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 }
Jerry Zhang487be612016-10-24 12:10:41 -0700516 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 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700521 } 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 LOG(ERROR) << "Mtp got unexpected short packet";
525 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700526 } else {
527 file_length -= ret;
528 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700529
530 if (write_error) {
531 cancelTransaction();
532 return -1;
533 }
534
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700535 // Enqueue a new write request
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700536 aio_prepare(&aio, mIobuf[i].bufs.data(), ret, offset);
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700537 aio_write(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700538
539 offset += ret;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700540 i = (i + 1) % NUM_IO_BUFS;
541 has_write = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700542 }
543 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700544 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) {
Jerry Zhang54107562017-05-15 11:54:19 -0700548 return -1;
549 }
550 }
Jerry Zhang487be612016-10-24 12:10:41 -0700551 return 0;
552}
553
Jerry Zhang487be612016-10-24 12:10:41 -0700554int 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));
Jerry Zhang44180302017-02-03 16:31:31 -0800558 uint64_t offset = mfr.offset;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700559 int packet_size = getPacketSize(mBulkIn);
Jerry Zhang487be612016-10-24 12:10:41 -0700560
Jerry Zhang44180302017-02-03 16:31:31 -0800561 // 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);
Jerry Zhang487be612016-10-24 12:10:41 -0700565
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700566 advise(mfr.fd);
Jerry Zhange9d94422017-01-18 12:03:56 -0800567
Jerry Zhang487be612016-10-24 12:10:41 -0700568 struct aiocb aio;
569 aio.aio_fildes = mfr.fd;
570 struct aiocb *aiol[] = {&aio};
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700571 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;
Jerry Zhang487be612016-10-24 12:10:41 -0700577
578 // Send the header data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700579 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);
Jerry Zhang487be612016-10-24 12:10:41 -0700584
585 // Some hosts don't support header/data separation even though MTP allows it
586 // Handle by filling first packet with initial file data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700587 if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
Jerry Zhang487be612016-10-24 12:10:41 -0700588 sizeof(mtp_data_header), init_read_len, offset))
589 != init_read_len) return -1;
Jerry Zhang297912b2018-05-11 11:29:54 -0700590 if (doAsync(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len,
591 false, false /* zlps are handled below */) == -1)
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700592 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700593 file_length -= init_read_len;
594 offset += init_read_len;
Jerry Zhang54107562017-05-15 11:54:19 -0700595 ret = init_read_len + sizeof(mtp_data_header);
Jerry Zhang487be612016-10-24 12:10:41 -0700596
Jerry Zhang487be612016-10-24 12:10:41 -0700597 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700598 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);
Jerry Zhang487be612016-10-24 12:10:41 -0700604 }
605
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700606 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;
Jerry Zhang7063c932017-04-04 15:06:10 -0700616 }
617
Jerry Zhang487be612016-10-24 12:10:41 -0700618 if (file_length > 0) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700619 // 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 PLOG(ERROR) << "Mtp error reading from disk";
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;
Jerry Zhang487be612016-10-24 12:10:41 -0700642 }
643
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700644 i = (i + 1) % NUM_IO_BUFS;
Jerry Zhang487be612016-10-24 12:10:41 -0700645 }
646
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700647 if (ret % packet_size == 0) {
Jerry Zhang487be612016-10-24 12:10:41 -0700648 // If the last packet wasn't short, send a final empty packet
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700649 if (write(mIobuf[0].bufs.data(), 0) != 0) {
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700650 return -1;
651 }
Jerry Zhang487be612016-10-24 12:10:41 -0700652 }
Jerry Zhang487be612016-10-24 12:10:41 -0700653 return 0;
654}
655
656int MtpFfsHandle::sendEvent(mtp_event me) {
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700657 // 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;
Jerry Zhang008f4df2017-08-09 17:53:50 -0700662 std::thread t([this, me]() { return this->doSendEvent(me); });
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700663 t.detach();
664 return 0;
665}
666
667void MtpFfsHandle::doSendEvent(mtp_event me) {
Jerry Zhang487be612016-10-24 12:10:41 -0700668 unsigned length = me.length;
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700669 int ret = ::write(mIntr, me.data, length);
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700670 if (static_cast<unsigned>(ret) != length)
671 PLOG(ERROR) << "Mtp error sending event thread!";
Jerry Zhang008f4df2017-08-09 17:53:50 -0700672 delete[] reinterpret_cast<char*>(me.data);
Jerry Zhang487be612016-10-24 12:10:41 -0700673}
674
675} // namespace android
676