blob: 952b9074d40fd0819a241e1ff5605f2934e3b8ae [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 Zhangdf69dd32017-05-03 17:17:49 -0700130int MtpFfsHandle::doAsync(void* data, size_t len, bool read) {
131 struct io_event ioevs[1];
132 if (len > AIO_BUF_LEN) {
133 LOG(ERROR) << "Mtp read/write too large " << len;
134 errno = EINVAL;
135 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700136 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700137 mIobuf[0].buf[0] = reinterpret_cast<unsigned char*>(data);
138 if (iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, len, read) == -1)
139 return -1;
140 int ret = waitEvents(&mIobuf[0], 1, ioevs, nullptr);
141 mIobuf[0].buf[0] = mIobuf[0].bufs.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700142 return ret;
143}
144
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700145int MtpFfsHandle::read(void* data, size_t len) {
146 return doAsync(data, len, true);
147}
148
149int MtpFfsHandle::write(const void* data, size_t len) {
150 return doAsync(const_cast<void*>(data), len, false);
151}
152
153int MtpFfsHandle::handleEvent() {
154
155 std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
156 usb_functionfs_event *event = events.data();
157 int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
158 events.size() * sizeof(usb_functionfs_event)));
159 if (nbytes == -1) {
160 return -1;
161 }
Jerry Zhang487be612016-10-24 12:10:41 -0700162 int ret = 0;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700163 for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
164 switch (event->type) {
165 case FUNCTIONFS_BIND:
166 case FUNCTIONFS_ENABLE:
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700167 ret = 0;
168 errno = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700169 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700170 case FUNCTIONFS_UNBIND:
171 case FUNCTIONFS_DISABLE:
172 errno = ESHUTDOWN;
173 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700174 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700175 case FUNCTIONFS_SETUP:
176 if (handleControlRequest(&event->u.setup) == -1)
177 ret = -1;
178 break;
Jerry Zhang63dac452017-12-06 15:19:36 -0800179 case FUNCTIONFS_SUSPEND:
180 case FUNCTIONFS_RESUME:
181 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700182 default:
183 LOG(ERROR) << "Mtp Event " << event->type << " (unknown)";
184 }
Jerry Zhang487be612016-10-24 12:10:41 -0700185 }
186 return ret;
187}
188
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700189int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
190 uint8_t type = setup->bRequestType;
191 uint8_t code = setup->bRequest;
192 uint16_t length = setup->wLength;
193 uint16_t index = setup->wIndex;
194 uint16_t value = setup->wValue;
195 std::vector<char> buf;
196 buf.resize(length);
197 int ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700198
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700199 if (!(type & USB_DIR_IN)) {
200 if (::read(mControl, buf.data(), length) != length) {
201 PLOG(ERROR) << "Mtp error ctrlreq read data";
202 }
203 }
204
205 if ((type & USB_TYPE_MASK) == USB_TYPE_CLASS && index == 0 && value == 0) {
206 switch(code) {
207 case MTP_REQ_RESET:
208 case MTP_REQ_CANCEL:
209 errno = ECANCELED;
210 ret = -1;
211 break;
212 case MTP_REQ_GET_DEVICE_STATUS:
213 {
214 if (length < sizeof(struct mtp_device_status) + 4) {
215 errno = EINVAL;
216 return -1;
217 }
218 struct mtp_device_status *st = reinterpret_cast<struct mtp_device_status*>(buf.data());
219 st->wLength = htole16(sizeof(st));
220 if (mCanceled) {
221 st->wLength += 4;
222 st->wCode = MTP_RESPONSE_TRANSACTION_CANCELLED;
223 uint16_t *endpoints = reinterpret_cast<uint16_t*>(st + 1);
224 endpoints[0] = ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_REVMAP);
225 endpoints[1] = ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_REVMAP);
226 mCanceled = false;
227 } else {
228 st->wCode = MTP_RESPONSE_OK;
229 }
230 length = st->wLength;
231 break;
232 }
233 default:
234 LOG(ERROR) << "Unrecognized Mtp class request! " << code;
235 }
236 } else {
237 LOG(ERROR) << "Unrecognized request type " << type;
238 }
239
240 if (type & USB_DIR_IN) {
241 if (::write(mControl, buf.data(), length) != length) {
242 PLOG(ERROR) << "Mtp error ctrlreq write data";
243 }
244 }
245 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700246}
247
Jerry Zhang63dac452017-12-06 15:19:36 -0800248int MtpFfsHandle::start(bool ptp) {
249 if (!openEndpoints(ptp))
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800250 return -1;
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800251
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700252 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
253 mIobuf[i].bufs.resize(MAX_FILE_CHUNK_SIZE);
254 mIobuf[i].iocb.resize(AIO_BUFS_MAX);
255 mIobuf[i].iocbs.resize(AIO_BUFS_MAX);
256 mIobuf[i].buf.resize(AIO_BUFS_MAX);
257 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
258 mIobuf[i].buf[j] = mIobuf[i].bufs.data() + j * AIO_BUF_LEN;
259 mIobuf[i].iocb[j] = &mIobuf[i].iocbs[j];
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800260 }
261 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700262
263 memset(&mCtx, 0, sizeof(mCtx));
264 if (io_setup(AIO_BUFS_MAX, &mCtx) < 0) {
265 PLOG(ERROR) << "unable to setup aio";
266 return -1;
267 }
268 mEventFd.reset(eventfd(0, EFD_NONBLOCK));
269 mPollFds[0].fd = mControl;
270 mPollFds[0].events = POLLIN;
271 mPollFds[1].fd = mEventFd;
272 mPollFds[1].events = POLLIN;
273
274 mCanceled = false;
Jerry Zhangb4f54262017-02-02 18:14:33 -0800275 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700276}
277
Jerry Zhang487be612016-10-24 12:10:41 -0700278void MtpFfsHandle::close() {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700279 io_destroy(mCtx);
Jerry Zhang487be612016-10-24 12:10:41 -0700280 closeEndpoints();
Jerry Zhang63dac452017-12-06 15:19:36 -0800281 closeConfig();
Jerry Zhang487be612016-10-24 12:10:41 -0700282}
283
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700284int MtpFfsHandle::waitEvents(struct io_buffer *buf, int min_events, struct io_event *events,
285 int *counter) {
286 int num_events = 0;
287 int ret = 0;
288 int error = 0;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700289
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700290 while (num_events < min_events) {
291 if (poll(mPollFds, 2, 0) == -1) {
292 PLOG(ERROR) << "Mtp error during poll()";
293 return -1;
294 }
295 if (mPollFds[0].revents & POLLIN) {
296 mPollFds[0].revents = 0;
297 if (handleEvent() == -1) {
298 error = errno;
299 }
300 }
301 if (mPollFds[1].revents & POLLIN) {
302 mPollFds[1].revents = 0;
303 uint64_t ev_cnt = 0;
304
305 if (::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1) {
306 PLOG(ERROR) << "Mtp unable to read eventfd";
307 error = errno;
308 continue;
309 }
310
311 // It's possible that io_getevents will return more events than the eventFd reported,
312 // since events may appear in the time between the calls. In this case, the eventFd will
313 // show up as readable next iteration, but there will be fewer or no events to actually
314 // wait for. Thus we never want io_getevents to block.
315 int this_events = TEMP_FAILURE_RETRY(io_getevents(mCtx, 0, AIO_BUFS_MAX, events, &ZERO_TIMEOUT));
316 if (this_events == -1) {
317 PLOG(ERROR) << "Mtp error getting events";
318 error = errno;
319 }
320 // Add up the total amount of data and find errors on the way.
321 for (unsigned j = 0; j < static_cast<unsigned>(this_events); j++) {
322 if (events[j].res < 0) {
323 errno = -events[j].res;
324 PLOG(ERROR) << "Mtp got error event at " << j << " and " << buf->actual << " total";
325 error = errno;
326 }
327 ret += events[j].res;
328 }
329 num_events += this_events;
330 if (counter)
331 *counter += this_events;
332 }
333 if (error) {
334 errno = error;
335 ret = -1;
336 break;
337 }
338 }
339 return ret;
340}
341
342void MtpFfsHandle::cancelTransaction() {
343 // Device cancels by stalling both bulk endpoints.
344 if (::read(mBulkIn, nullptr, 0) != -1 || errno != EBADMSG)
345 PLOG(ERROR) << "Mtp stall failed on bulk in";
346 if (::write(mBulkOut, nullptr, 0) != -1 || errno != EBADMSG)
347 PLOG(ERROR) << "Mtp stall failed on bulk out";
348 mCanceled = true;
349 errno = ECANCELED;
350}
351
352int MtpFfsHandle::cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start,
353 unsigned end) {
354 // Some manpages for io_cancel are out of date and incorrect.
355 // io_cancel will return -EINPROGRESS on success and does
356 // not place the event in the given memory. We have to use
357 // io_getevents to wait for all the events we cancelled.
358 int ret = 0;
359 unsigned num_events = 0;
360 int save_errno = errno;
361 errno = 0;
362
363 for (unsigned j = start; j < end; j++) {
364 if (io_cancel(mCtx, iocb[j], nullptr) != -1 || errno != EINPROGRESS) {
365 PLOG(ERROR) << "Mtp couldn't cancel request " << j;
366 } else {
367 num_events++;
368 }
369 }
370 if (num_events != end - start) {
371 ret = -1;
372 errno = EIO;
373 }
374 int evs = TEMP_FAILURE_RETRY(io_getevents(mCtx, num_events, AIO_BUFS_MAX, events, nullptr));
375 if (static_cast<unsigned>(evs) != num_events) {
376 PLOG(ERROR) << "Mtp couldn't cancel all requests, got " << evs;
377 ret = -1;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700378 }
Jerry Zhang487be612016-10-24 12:10:41 -0700379
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700380 uint64_t ev_cnt = 0;
381 if (num_events && ::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1)
382 PLOG(ERROR) << "Mtp Unable to read event fd";
383
384 if (ret == 0) {
385 // Restore errno since it probably got overriden with EINPROGRESS.
386 errno = save_errno;
387 }
388 return ret;
389}
390
391int MtpFfsHandle::iobufSubmit(struct io_buffer *buf, int fd, unsigned length, bool read) {
392 int ret = 0;
393 buf->actual = AIO_BUFS_MAX;
394 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
395 unsigned rq_length = std::min(AIO_BUF_LEN, length - AIO_BUF_LEN * j);
396 io_prep(buf->iocb[j], fd, buf->buf[j], rq_length, 0, read);
397 buf->iocb[j]->aio_flags |= IOCB_FLAG_RESFD;
398 buf->iocb[j]->aio_resfd = mEventFd;
399
400 // Not enough data, so table is truncated.
401 if (rq_length < AIO_BUF_LEN || length == AIO_BUF_LEN * (j + 1)) {
402 buf->actual = j + 1;
403 break;
404 }
405 }
406
407 ret = io_submit(mCtx, buf->actual, buf->iocb.data());
408 if (ret != static_cast<int>(buf->actual)) {
409 PLOG(ERROR) << "Mtp io_submit got " << ret << " expected " << buf->actual;
410 if (ret != -1) {
411 errno = EIO;
412 }
413 ret = -1;
414 }
415 return ret;
416}
417
418int MtpFfsHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
419 // When receiving files, the incoming length is given in 32 bits.
420 // A >=4G file is given as 0xFFFFFFFF
421 uint32_t file_length = mfr.length;
422 uint64_t offset = mfr.offset;
Jerry Zhang487be612016-10-24 12:10:41 -0700423
424 struct aiocb aio;
425 aio.aio_fildes = mfr.fd;
426 aio.aio_buf = nullptr;
427 struct aiocb *aiol[] = {&aio};
Jerry Zhang487be612016-10-24 12:10:41 -0700428
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700429 int ret = -1;
430 unsigned i = 0;
431 size_t length;
432 struct io_event ioevs[AIO_BUFS_MAX];
433 bool has_write = false;
434 bool error = false;
435 bool write_error = false;
436 int packet_size = getPacketSize(mBulkOut);
437 bool short_packet = false;
438 advise(mfr.fd);
Jerry Zhang487be612016-10-24 12:10:41 -0700439
440 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700441 while (file_length > 0 || has_write) {
442 // Queue an asynchronous read from USB.
Jerry Zhang487be612016-10-24 12:10:41 -0700443 if (file_length > 0) {
444 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700445 if (iobufSubmit(&mIobuf[i], mBulkOut, length, true) == -1)
446 error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700447 }
448
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700449 // Get the return status of the last write request.
450 if (has_write) {
Jerry Zhang487be612016-10-24 12:10:41 -0700451 aio_suspend(aiol, 1, nullptr);
Jerry Zhang487be612016-10-24 12:10:41 -0700452 int written = aio_return(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700453 if (static_cast<size_t>(written) < aio.aio_nbytes) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700454 errno = written == -1 ? aio_error(&aio) : EIO;
455 PLOG(ERROR) << "Mtp error writing to disk";
456 write_error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700457 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700458 has_write = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700459 }
460
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700461 if (error) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700462 return -1;
463 }
464
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700465 // Get the result of the read request, and queue a write to disk.
466 if (file_length > 0) {
467 unsigned num_events = 0;
468 ret = 0;
469 unsigned short_i = mIobuf[i].actual;
470 while (num_events < short_i) {
471 // Get all events up to the short read, if there is one.
472 // We must wait for each event since data transfer could end at any time.
473 int this_events = 0;
474 int event_ret = waitEvents(&mIobuf[i], 1, ioevs, &this_events);
475 num_events += this_events;
476
477 if (event_ret == -1) {
478 cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual);
479 return -1;
480 }
481 ret += event_ret;
482 for (int j = 0; j < this_events; j++) {
483 // struct io_event contains a pointer to the associated struct iocb as a __u64.
484 if (static_cast<__u64>(ioevs[j].res) <
485 reinterpret_cast<struct iocb*>(ioevs[j].obj)->aio_nbytes) {
486 // We've found a short event. Store the index since
487 // events won't necessarily arrive in the order they are queued.
488 short_i = (ioevs[j].obj - reinterpret_cast<uint64_t>(mIobuf[i].iocbs.data()))
489 / sizeof(struct iocb) + 1;
490 short_packet = true;
491 }
492 }
493 }
494 if (short_packet) {
495 if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual)) {
496 write_error = true;
497 }
498 }
Jerry Zhang487be612016-10-24 12:10:41 -0700499 if (file_length == MAX_MTP_FILE_SIZE) {
500 // For larger files, receive until a short packet is received.
501 if (static_cast<size_t>(ret) < length) {
502 file_length = 0;
503 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700504 } else if (ret < static_cast<int>(length)) {
505 // If file is less than 4G and we get a short packet, it's an error.
506 errno = EIO;
507 LOG(ERROR) << "Mtp got unexpected short packet";
508 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700509 } else {
510 file_length -= ret;
511 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700512
513 if (write_error) {
514 cancelTransaction();
515 return -1;
516 }
517
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700518 // Enqueue a new write request
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700519 aio_prepare(&aio, mIobuf[i].bufs.data(), ret, offset);
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700520 aio_write(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700521
522 offset += ret;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700523 i = (i + 1) % NUM_IO_BUFS;
524 has_write = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700525 }
526 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700527 if ((ret % packet_size == 0 && !short_packet) || zero_packet) {
528 // Receive an empty packet if size is a multiple of the endpoint size
529 // and we didn't already get an empty packet from the header or large file.
530 if (read(mIobuf[0].bufs.data(), packet_size) != 0) {
Jerry Zhang54107562017-05-15 11:54:19 -0700531 return -1;
532 }
533 }
Jerry Zhang487be612016-10-24 12:10:41 -0700534 return 0;
535}
536
Jerry Zhang487be612016-10-24 12:10:41 -0700537int MtpFfsHandle::sendFile(mtp_file_range mfr) {
538 uint64_t file_length = mfr.length;
539 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
540 file_length + sizeof(mtp_data_header));
Jerry Zhang44180302017-02-03 16:31:31 -0800541 uint64_t offset = mfr.offset;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700542 int packet_size = getPacketSize(mBulkIn);
Jerry Zhang487be612016-10-24 12:10:41 -0700543
Jerry Zhang44180302017-02-03 16:31:31 -0800544 // If file_length is larger than a size_t, truncating would produce the wrong comparison.
545 // Instead, promote the left side to 64 bits, then truncate the small result.
546 int init_read_len = std::min(
547 static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700548
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700549 advise(mfr.fd);
Jerry Zhange9d94422017-01-18 12:03:56 -0800550
Jerry Zhang487be612016-10-24 12:10:41 -0700551 struct aiocb aio;
552 aio.aio_fildes = mfr.fd;
553 struct aiocb *aiol[] = {&aio};
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700554 int ret = 0;
555 int length, num_read;
556 unsigned i = 0;
557 struct io_event ioevs[AIO_BUFS_MAX];
558 bool error = false;
559 bool has_write = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700560
561 // Send the header data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700562 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(mIobuf[0].bufs.data());
563 header->length = htole32(given_length);
564 header->type = htole16(2); // data packet
565 header->command = htole16(mfr.command);
566 header->transaction_id = htole32(mfr.transaction_id);
Jerry Zhang487be612016-10-24 12:10:41 -0700567
568 // Some hosts don't support header/data separation even though MTP allows it
569 // Handle by filling first packet with initial file data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700570 if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
Jerry Zhang487be612016-10-24 12:10:41 -0700571 sizeof(mtp_data_header), init_read_len, offset))
572 != init_read_len) return -1;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700573 if (write(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len) == -1)
574 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700575 file_length -= init_read_len;
576 offset += init_read_len;
Jerry Zhang54107562017-05-15 11:54:19 -0700577 ret = init_read_len + sizeof(mtp_data_header);
Jerry Zhang487be612016-10-24 12:10:41 -0700578
Jerry Zhang487be612016-10-24 12:10:41 -0700579 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700580 while(file_length > 0 || has_write) {
581 if (file_length > 0) {
582 // Queue up a read from disk.
583 length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
584 aio_prepare(&aio, mIobuf[i].bufs.data(), length, offset);
585 aio_read(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700586 }
587
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700588 if (has_write) {
589 // Wait for usb write. Cancel unwritten portion if there's an error.
590 int num_events = 0;
591 if (waitEvents(&mIobuf[(i-1)%NUM_IO_BUFS], mIobuf[(i-1)%NUM_IO_BUFS].actual, ioevs,
592 &num_events) != ret) {
593 error = true;
594 cancelEvents(mIobuf[(i-1)%NUM_IO_BUFS].iocb.data(), ioevs, num_events,
595 mIobuf[(i-1)%NUM_IO_BUFS].actual);
596 }
597 has_write = false;
Jerry Zhang7063c932017-04-04 15:06:10 -0700598 }
599
Jerry Zhang487be612016-10-24 12:10:41 -0700600 if (file_length > 0) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700601 // Wait for the previous read to finish
602 aio_suspend(aiol, 1, nullptr);
603 num_read = aio_return(&aio);
604 if (static_cast<size_t>(num_read) < aio.aio_nbytes) {
605 errno = num_read == -1 ? aio_error(&aio) : EIO;
606 PLOG(ERROR) << "Mtp error reading from disk";
607 cancelTransaction();
608 return -1;
609 }
610
611 file_length -= num_read;
612 offset += num_read;
613
614 if (error) {
615 return -1;
616 }
617
618 // Queue up a write to usb.
619 if (iobufSubmit(&mIobuf[i], mBulkIn, num_read, false) == -1) {
620 return -1;
621 }
622 has_write = true;
623 ret = num_read;
Jerry Zhang487be612016-10-24 12:10:41 -0700624 }
625
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700626 i = (i + 1) % NUM_IO_BUFS;
Jerry Zhang487be612016-10-24 12:10:41 -0700627 }
628
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700629 if (ret % packet_size == 0) {
Jerry Zhang487be612016-10-24 12:10:41 -0700630 // If the last packet wasn't short, send a final empty packet
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700631 if (write(mIobuf[0].bufs.data(), 0) != 0) {
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700632 return -1;
633 }
Jerry Zhang487be612016-10-24 12:10:41 -0700634 }
Jerry Zhang487be612016-10-24 12:10:41 -0700635 return 0;
636}
637
638int MtpFfsHandle::sendEvent(mtp_event me) {
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700639 // Mimic the behavior of f_mtp by sending the event async.
640 // Events aren't critical to the connection, so we don't need to check the return value.
641 char *temp = new char[me.length];
642 memcpy(temp, me.data, me.length);
643 me.data = temp;
Jerry Zhang008f4df2017-08-09 17:53:50 -0700644 std::thread t([this, me]() { return this->doSendEvent(me); });
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700645 t.detach();
646 return 0;
647}
648
649void MtpFfsHandle::doSendEvent(mtp_event me) {
Jerry Zhang487be612016-10-24 12:10:41 -0700650 unsigned length = me.length;
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700651 int ret = ::write(mIntr, me.data, length);
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700652 if (static_cast<unsigned>(ret) != length)
653 PLOG(ERROR) << "Mtp error sending event thread!";
Jerry Zhang008f4df2017-08-09 17:53:50 -0700654 delete[] reinterpret_cast<char*>(me.data);
Jerry Zhang487be612016-10-24 12:10:41 -0700655}
656
657} // namespace android
658