blob: 89b20e5b8698309a35f5dd4dd6252059d936e915 [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>
23#include <linux/usb/ch9.h>
24#include <linux/usb/functionfs.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070025#include <memory>
Jerry Zhang487be612016-10-24 12:10:41 -070026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/endian.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070030#include <sys/eventfd.h>
Jerry Zhang487be612016-10-24 12:10:41 -070031#include <sys/ioctl.h>
Jerry Zhange9d94422017-01-18 12:03:56 -080032#include <sys/mman.h>
Jerry Zhangdf69dd32017-05-03 17:17:49 -070033#include <sys/poll.h>
Jerry Zhang487be612016-10-24 12:10:41 -070034#include <sys/stat.h>
35#include <sys/types.h>
36#include <unistd.h>
Jerry Zhang487be612016-10-24 12:10:41 -070037
Jerry Zhangdf69dd32017-05-03 17:17:49 -070038#include "PosixAsyncIO.h"
Jerry Zhang487be612016-10-24 12:10:41 -070039#include "MtpFfsHandle.h"
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -080040#include "mtp.h"
Jerry Zhang487be612016-10-24 12:10:41 -070041
Jerry Zhang487be612016-10-24 12:10:41 -070042namespace {
43
44constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
45constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
46constexpr char FFS_MTP_EP_INTR[] = "/dev/usb-ffs/mtp/ep3";
47
48constexpr int MAX_PACKET_SIZE_FS = 64;
49constexpr int MAX_PACKET_SIZE_HS = 512;
50constexpr int MAX_PACKET_SIZE_SS = 1024;
Jerry Zhangdf69dd32017-05-03 17:17:49 -070051constexpr int MAX_PACKET_SIZE_EV = 28;
Jerry Zhang487be612016-10-24 12:10:41 -070052
Jerry Zhangdf69dd32017-05-03 17:17:49 -070053constexpr unsigned AIO_BUFS_MAX = 128;
54constexpr unsigned AIO_BUF_LEN = 16384;
Jerry Zhang487be612016-10-24 12:10:41 -070055
Jerry Zhangdf69dd32017-05-03 17:17:49 -070056constexpr unsigned FFS_NUM_EVENTS = 5;
Jerry Zhang487be612016-10-24 12:10:41 -070057
Jerry Zhangdf69dd32017-05-03 17:17:49 -070058constexpr unsigned MAX_FILE_CHUNK_SIZE = AIO_BUFS_MAX * AIO_BUF_LEN;
Jerry Zhangb4f54262017-02-02 18:14:33 -080059
Jerry Zhangdf69dd32017-05-03 17:17:49 -070060constexpr uint32_t MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
Jerry Zhang487be612016-10-24 12:10:41 -070061
Jerry Zhangdf69dd32017-05-03 17:17:49 -070062struct timespec ZERO_TIMEOUT = { 0, 0 };
Jerry Zhangb4f54262017-02-02 18:14:33 -080063
Jerry Zhang487be612016-10-24 12:10:41 -070064struct func_desc {
65 struct usb_interface_descriptor intf;
66 struct usb_endpoint_descriptor_no_audio sink;
67 struct usb_endpoint_descriptor_no_audio source;
68 struct usb_endpoint_descriptor_no_audio intr;
69} __attribute__((packed));
70
71struct ss_func_desc {
72 struct usb_interface_descriptor intf;
73 struct usb_endpoint_descriptor_no_audio sink;
74 struct usb_ss_ep_comp_descriptor sink_comp;
75 struct usb_endpoint_descriptor_no_audio source;
76 struct usb_ss_ep_comp_descriptor source_comp;
77 struct usb_endpoint_descriptor_no_audio intr;
78 struct usb_ss_ep_comp_descriptor intr_comp;
79} __attribute__((packed));
80
81struct desc_v1 {
82 struct usb_functionfs_descs_head_v1 {
83 __le32 magic;
84 __le32 length;
85 __le32 fs_count;
86 __le32 hs_count;
87 } __attribute__((packed)) header;
88 struct func_desc fs_descs, hs_descs;
89} __attribute__((packed));
90
91struct desc_v2 {
92 struct usb_functionfs_descs_head_v2 header;
93 // The rest of the structure depends on the flags in the header.
94 __le32 fs_count;
95 __le32 hs_count;
96 __le32 ss_count;
97 struct func_desc fs_descs, hs_descs;
98 struct ss_func_desc ss_descs;
99} __attribute__((packed));
100
101const struct usb_interface_descriptor mtp_interface_desc = {
102 .bLength = USB_DT_INTERFACE_SIZE,
103 .bDescriptorType = USB_DT_INTERFACE,
104 .bInterfaceNumber = 0,
105 .bNumEndpoints = 3,
106 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
107 .bInterfaceSubClass = 1,
108 .bInterfaceProtocol = 1,
Jerry Zhang6a790522017-01-11 15:17:53 -0800109 .iInterface = 1,
Jerry Zhang487be612016-10-24 12:10:41 -0700110};
111
112const struct usb_interface_descriptor ptp_interface_desc = {
113 .bLength = USB_DT_INTERFACE_SIZE,
114 .bDescriptorType = USB_DT_INTERFACE,
115 .bInterfaceNumber = 0,
116 .bNumEndpoints = 3,
117 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
118 .bInterfaceSubClass = 1,
119 .bInterfaceProtocol = 1,
120};
121
122const struct usb_endpoint_descriptor_no_audio fs_sink = {
123 .bLength = USB_DT_ENDPOINT_SIZE,
124 .bDescriptorType = USB_DT_ENDPOINT,
125 .bEndpointAddress = 1 | USB_DIR_IN,
126 .bmAttributes = USB_ENDPOINT_XFER_BULK,
127 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
128};
129
130const struct usb_endpoint_descriptor_no_audio fs_source = {
131 .bLength = USB_DT_ENDPOINT_SIZE,
132 .bDescriptorType = USB_DT_ENDPOINT,
133 .bEndpointAddress = 2 | USB_DIR_OUT,
134 .bmAttributes = USB_ENDPOINT_XFER_BULK,
135 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
136};
137
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700138const struct usb_endpoint_descriptor_no_audio intr = {
Jerry Zhang487be612016-10-24 12:10:41 -0700139 .bLength = USB_DT_ENDPOINT_SIZE,
140 .bDescriptorType = USB_DT_ENDPOINT,
141 .bEndpointAddress = 3 | USB_DIR_IN,
142 .bmAttributes = USB_ENDPOINT_XFER_INT,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700143 .wMaxPacketSize = MAX_PACKET_SIZE_EV,
Jerry Zhang487be612016-10-24 12:10:41 -0700144 .bInterval = 6,
145};
146
147const struct usb_endpoint_descriptor_no_audio hs_sink = {
148 .bLength = USB_DT_ENDPOINT_SIZE,
149 .bDescriptorType = USB_DT_ENDPOINT,
150 .bEndpointAddress = 1 | USB_DIR_IN,
151 .bmAttributes = USB_ENDPOINT_XFER_BULK,
152 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
153};
154
155const struct usb_endpoint_descriptor_no_audio hs_source = {
156 .bLength = USB_DT_ENDPOINT_SIZE,
157 .bDescriptorType = USB_DT_ENDPOINT,
158 .bEndpointAddress = 2 | USB_DIR_OUT,
159 .bmAttributes = USB_ENDPOINT_XFER_BULK,
160 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
161};
162
Jerry Zhang487be612016-10-24 12:10:41 -0700163const struct usb_endpoint_descriptor_no_audio ss_sink = {
164 .bLength = USB_DT_ENDPOINT_SIZE,
165 .bDescriptorType = USB_DT_ENDPOINT,
166 .bEndpointAddress = 1 | USB_DIR_IN,
167 .bmAttributes = USB_ENDPOINT_XFER_BULK,
168 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
169};
170
171const struct usb_endpoint_descriptor_no_audio ss_source = {
172 .bLength = USB_DT_ENDPOINT_SIZE,
173 .bDescriptorType = USB_DT_ENDPOINT,
174 .bEndpointAddress = 2 | USB_DIR_OUT,
175 .bmAttributes = USB_ENDPOINT_XFER_BULK,
176 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
177};
178
Jerry Zhang487be612016-10-24 12:10:41 -0700179const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
180 .bLength = sizeof(ss_sink_comp),
181 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800182 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700183};
184
185const struct usb_ss_ep_comp_descriptor ss_source_comp = {
186 .bLength = sizeof(ss_source_comp),
187 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800188 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700189};
190
191const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
192 .bLength = sizeof(ss_intr_comp),
193 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
194};
195
196const struct func_desc mtp_fs_descriptors = {
197 .intf = mtp_interface_desc,
198 .sink = fs_sink,
199 .source = fs_source,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700200 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700201};
202
203const struct func_desc mtp_hs_descriptors = {
204 .intf = mtp_interface_desc,
205 .sink = hs_sink,
206 .source = hs_source,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700207 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700208};
209
210const struct ss_func_desc mtp_ss_descriptors = {
211 .intf = mtp_interface_desc,
212 .sink = ss_sink,
213 .sink_comp = ss_sink_comp,
214 .source = ss_source,
215 .source_comp = ss_source_comp,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700216 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700217 .intr_comp = ss_intr_comp,
218};
219
220const struct func_desc ptp_fs_descriptors = {
221 .intf = ptp_interface_desc,
222 .sink = fs_sink,
223 .source = fs_source,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700224 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700225};
226
227const struct func_desc ptp_hs_descriptors = {
228 .intf = ptp_interface_desc,
229 .sink = hs_sink,
230 .source = hs_source,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700231 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700232};
233
234const struct ss_func_desc ptp_ss_descriptors = {
235 .intf = ptp_interface_desc,
236 .sink = ss_sink,
237 .sink_comp = ss_sink_comp,
238 .source = ss_source,
239 .source_comp = ss_source_comp,
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700240 .intr = intr,
Jerry Zhang487be612016-10-24 12:10:41 -0700241 .intr_comp = ss_intr_comp,
242};
243
Jerry Zhang6a790522017-01-11 15:17:53 -0800244#define STR_INTERFACE "MTP"
Jerry Zhang487be612016-10-24 12:10:41 -0700245const struct {
246 struct usb_functionfs_strings_head header;
Jerry Zhang6a790522017-01-11 15:17:53 -0800247 struct {
248 __le16 code;
249 const char str1[sizeof(STR_INTERFACE)];
250 } __attribute__((packed)) lang0;
Jerry Zhang487be612016-10-24 12:10:41 -0700251} __attribute__((packed)) strings = {
252 .header = {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700253 .magic = htole32(FUNCTIONFS_STRINGS_MAGIC),
254 .length = htole32(sizeof(strings)),
255 .str_count = htole32(1),
256 .lang_count = htole32(1),
Jerry Zhang6a790522017-01-11 15:17:53 -0800257 },
258 .lang0 = {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700259 .code = htole16(0x0409),
Jerry Zhang6a790522017-01-11 15:17:53 -0800260 .str1 = STR_INTERFACE,
Jerry Zhang487be612016-10-24 12:10:41 -0700261 },
262};
263
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700264struct mtp_device_status {
265 uint16_t wLength;
266 uint16_t wCode;
267};
268
Jerry Zhang487be612016-10-24 12:10:41 -0700269} // anonymous namespace
270
271namespace android {
272
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700273int MtpFfsHandle::getPacketSize(int ffs_fd) {
274 struct usb_endpoint_descriptor desc;
275 if (ioctl(ffs_fd, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&desc))) {
276 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
277 return MAX_PACKET_SIZE_HS;
278 } else {
279 return desc.wMaxPacketSize;
280 }
281}
282
283MtpFfsHandle::MtpFfsHandle() {}
Jerry Zhang487be612016-10-24 12:10:41 -0700284
285MtpFfsHandle::~MtpFfsHandle() {}
286
287void MtpFfsHandle::closeEndpoints() {
288 mIntr.reset();
289 mBulkIn.reset();
290 mBulkOut.reset();
291}
292
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700293bool MtpFfsHandle::openEndpoints() {
294 if (mBulkIn < 0) {
295 mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
296 if (mBulkIn < 0) {
297 PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
298 return false;
299 }
300 }
301
302 if (mBulkOut < 0) {
303 mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
304 if (mBulkOut < 0) {
305 PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
306 return false;
307 }
308 }
309
310 if (mIntr < 0) {
311 mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
312 if (mIntr < 0) {
313 PLOG(ERROR) << FFS_MTP_EP_INTR << ": cannot open intr ep";
314 return false;
315 }
316 }
317 return true;
318}
319
320void MtpFfsHandle::advise(int fd) {
321 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
322 if (posix_madvise(mIobuf[i].bufs.data(), MAX_FILE_CHUNK_SIZE,
323 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED) < 0)
324 PLOG(ERROR) << "Failed to madvise";
325 }
326 if (posix_fadvise(fd, 0, 0,
327 POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE | POSIX_FADV_WILLNEED) < 0)
328 PLOG(ERROR) << "Failed to fadvise";
329}
330
Jerry Zhang487be612016-10-24 12:10:41 -0700331bool MtpFfsHandle::initFunctionfs() {
332 ssize_t ret;
333 struct desc_v1 v1_descriptor;
334 struct desc_v2 v2_descriptor;
335
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700336 v2_descriptor.header.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
337 v2_descriptor.header.length = htole32(sizeof(v2_descriptor));
Jerry Zhang487be612016-10-24 12:10:41 -0700338 v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
339 FUNCTIONFS_HAS_SS_DESC;
340 v2_descriptor.fs_count = 4;
341 v2_descriptor.hs_count = 4;
342 v2_descriptor.ss_count = 7;
343 v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
344 v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
345 v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
346
347 if (mControl < 0) { // might have already done this before
348 mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
349 if (mControl < 0) {
350 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
351 goto err;
352 }
353
354 ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
355 if (ret < 0) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700356 v1_descriptor.header.magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC);
357 v1_descriptor.header.length = htole32(sizeof(v1_descriptor));
Jerry Zhang487be612016-10-24 12:10:41 -0700358 v1_descriptor.header.fs_count = 4;
359 v1_descriptor.header.hs_count = 4;
360 v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
361 v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
362 PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
363 ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
364 if (ret < 0) {
365 PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
366 goto err;
367 }
368 }
369 ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
370 if (ret < 0) {
371 PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
372 goto err;
373 }
374 }
Jerry Zhang487be612016-10-24 12:10:41 -0700375
Jerry Zhang487be612016-10-24 12:10:41 -0700376 return true;
377
378err:
Jerry Zhang487be612016-10-24 12:10:41 -0700379 closeConfig();
380 return false;
381}
382
383void MtpFfsHandle::closeConfig() {
384 mControl.reset();
385}
386
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700387int MtpFfsHandle::doAsync(void* data, size_t len, bool read) {
388 struct io_event ioevs[1];
389 if (len > AIO_BUF_LEN) {
390 LOG(ERROR) << "Mtp read/write too large " << len;
391 errno = EINVAL;
392 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700393 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700394 mIobuf[0].buf[0] = reinterpret_cast<unsigned char*>(data);
395 if (iobufSubmit(&mIobuf[0], read ? mBulkOut : mBulkIn, len, read) == -1)
396 return -1;
397 int ret = waitEvents(&mIobuf[0], 1, ioevs, nullptr);
398 mIobuf[0].buf[0] = mIobuf[0].bufs.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700399 return ret;
400}
401
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700402int MtpFfsHandle::read(void* data, size_t len) {
403 return doAsync(data, len, true);
404}
405
406int MtpFfsHandle::write(const void* data, size_t len) {
407 return doAsync(const_cast<void*>(data), len, false);
408}
409
410int MtpFfsHandle::handleEvent() {
411
412 std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
413 usb_functionfs_event *event = events.data();
414 int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
415 events.size() * sizeof(usb_functionfs_event)));
416 if (nbytes == -1) {
417 return -1;
418 }
Jerry Zhang487be612016-10-24 12:10:41 -0700419 int ret = 0;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700420 for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
421 switch (event->type) {
422 case FUNCTIONFS_BIND:
423 case FUNCTIONFS_ENABLE:
424 case FUNCTIONFS_RESUME:
425 ret = 0;
426 errno = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700427 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700428 case FUNCTIONFS_SUSPEND:
429 case FUNCTIONFS_UNBIND:
430 case FUNCTIONFS_DISABLE:
431 errno = ESHUTDOWN;
432 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700433 break;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700434 case FUNCTIONFS_SETUP:
435 if (handleControlRequest(&event->u.setup) == -1)
436 ret = -1;
437 break;
438 default:
439 LOG(ERROR) << "Mtp Event " << event->type << " (unknown)";
440 }
Jerry Zhang487be612016-10-24 12:10:41 -0700441 }
442 return ret;
443}
444
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700445int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
446 uint8_t type = setup->bRequestType;
447 uint8_t code = setup->bRequest;
448 uint16_t length = setup->wLength;
449 uint16_t index = setup->wIndex;
450 uint16_t value = setup->wValue;
451 std::vector<char> buf;
452 buf.resize(length);
453 int ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700454
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700455 if (!(type & USB_DIR_IN)) {
456 if (::read(mControl, buf.data(), length) != length) {
457 PLOG(ERROR) << "Mtp error ctrlreq read data";
458 }
459 }
460
461 if ((type & USB_TYPE_MASK) == USB_TYPE_CLASS && index == 0 && value == 0) {
462 switch(code) {
463 case MTP_REQ_RESET:
464 case MTP_REQ_CANCEL:
465 errno = ECANCELED;
466 ret = -1;
467 break;
468 case MTP_REQ_GET_DEVICE_STATUS:
469 {
470 if (length < sizeof(struct mtp_device_status) + 4) {
471 errno = EINVAL;
472 return -1;
473 }
474 struct mtp_device_status *st = reinterpret_cast<struct mtp_device_status*>(buf.data());
475 st->wLength = htole16(sizeof(st));
476 if (mCanceled) {
477 st->wLength += 4;
478 st->wCode = MTP_RESPONSE_TRANSACTION_CANCELLED;
479 uint16_t *endpoints = reinterpret_cast<uint16_t*>(st + 1);
480 endpoints[0] = ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_REVMAP);
481 endpoints[1] = ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_REVMAP);
482 mCanceled = false;
483 } else {
484 st->wCode = MTP_RESPONSE_OK;
485 }
486 length = st->wLength;
487 break;
488 }
489 default:
490 LOG(ERROR) << "Unrecognized Mtp class request! " << code;
491 }
492 } else {
493 LOG(ERROR) << "Unrecognized request type " << type;
494 }
495
496 if (type & USB_DIR_IN) {
497 if (::write(mControl, buf.data(), length) != length) {
498 PLOG(ERROR) << "Mtp error ctrlreq write data";
499 }
500 }
501 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700502}
503
504int MtpFfsHandle::start() {
505 mLock.lock();
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800506
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700507 if (!openEndpoints())
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800508 return -1;
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800509
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700510 for (unsigned i = 0; i < NUM_IO_BUFS; i++) {
511 mIobuf[i].bufs.resize(MAX_FILE_CHUNK_SIZE);
512 mIobuf[i].iocb.resize(AIO_BUFS_MAX);
513 mIobuf[i].iocbs.resize(AIO_BUFS_MAX);
514 mIobuf[i].buf.resize(AIO_BUFS_MAX);
515 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
516 mIobuf[i].buf[j] = mIobuf[i].bufs.data() + j * AIO_BUF_LEN;
517 mIobuf[i].iocb[j] = &mIobuf[i].iocbs[j];
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800518 }
519 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700520
521 memset(&mCtx, 0, sizeof(mCtx));
522 if (io_setup(AIO_BUFS_MAX, &mCtx) < 0) {
523 PLOG(ERROR) << "unable to setup aio";
524 return -1;
525 }
526 mEventFd.reset(eventfd(0, EFD_NONBLOCK));
527 mPollFds[0].fd = mControl;
528 mPollFds[0].events = POLLIN;
529 mPollFds[1].fd = mEventFd;
530 mPollFds[1].events = POLLIN;
531
532 mCanceled = false;
Jerry Zhangb4f54262017-02-02 18:14:33 -0800533 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700534}
535
536int MtpFfsHandle::configure(bool usePtp) {
537 // Wait till previous server invocation has closed
Jerry Zhang0475d912017-04-03 11:24:48 -0700538 if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) {
539 LOG(ERROR) << "MtpServer was unable to get configure lock";
540 return -1;
541 }
542 int ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700543
544 // If ptp is changed, the configuration must be rewritten
545 if (mPtp != usePtp) {
546 closeEndpoints();
547 closeConfig();
548 }
549 mPtp = usePtp;
550
551 if (!initFunctionfs()) {
Jerry Zhang0475d912017-04-03 11:24:48 -0700552 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700553 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700554
Jerry Zhang0475d912017-04-03 11:24:48 -0700555 mLock.unlock();
556 return ret;
Jerry Zhang487be612016-10-24 12:10:41 -0700557}
558
559void MtpFfsHandle::close() {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700560 io_destroy(mCtx);
Jerry Zhang487be612016-10-24 12:10:41 -0700561 closeEndpoints();
562 mLock.unlock();
563}
564
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700565int MtpFfsHandle::waitEvents(struct io_buffer *buf, int min_events, struct io_event *events,
566 int *counter) {
567 int num_events = 0;
568 int ret = 0;
569 int error = 0;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700570
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700571 while (num_events < min_events) {
572 if (poll(mPollFds, 2, 0) == -1) {
573 PLOG(ERROR) << "Mtp error during poll()";
574 return -1;
575 }
576 if (mPollFds[0].revents & POLLIN) {
577 mPollFds[0].revents = 0;
578 if (handleEvent() == -1) {
579 error = errno;
580 }
581 }
582 if (mPollFds[1].revents & POLLIN) {
583 mPollFds[1].revents = 0;
584 uint64_t ev_cnt = 0;
585
586 if (::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1) {
587 PLOG(ERROR) << "Mtp unable to read eventfd";
588 error = errno;
589 continue;
590 }
591
592 // It's possible that io_getevents will return more events than the eventFd reported,
593 // since events may appear in the time between the calls. In this case, the eventFd will
594 // show up as readable next iteration, but there will be fewer or no events to actually
595 // wait for. Thus we never want io_getevents to block.
596 int this_events = TEMP_FAILURE_RETRY(io_getevents(mCtx, 0, AIO_BUFS_MAX, events, &ZERO_TIMEOUT));
597 if (this_events == -1) {
598 PLOG(ERROR) << "Mtp error getting events";
599 error = errno;
600 }
601 // Add up the total amount of data and find errors on the way.
602 for (unsigned j = 0; j < static_cast<unsigned>(this_events); j++) {
603 if (events[j].res < 0) {
604 errno = -events[j].res;
605 PLOG(ERROR) << "Mtp got error event at " << j << " and " << buf->actual << " total";
606 error = errno;
607 }
608 ret += events[j].res;
609 }
610 num_events += this_events;
611 if (counter)
612 *counter += this_events;
613 }
614 if (error) {
615 errno = error;
616 ret = -1;
617 break;
618 }
619 }
620 return ret;
621}
622
623void MtpFfsHandle::cancelTransaction() {
624 // Device cancels by stalling both bulk endpoints.
625 if (::read(mBulkIn, nullptr, 0) != -1 || errno != EBADMSG)
626 PLOG(ERROR) << "Mtp stall failed on bulk in";
627 if (::write(mBulkOut, nullptr, 0) != -1 || errno != EBADMSG)
628 PLOG(ERROR) << "Mtp stall failed on bulk out";
629 mCanceled = true;
630 errno = ECANCELED;
631}
632
633int MtpFfsHandle::cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start,
634 unsigned end) {
635 // Some manpages for io_cancel are out of date and incorrect.
636 // io_cancel will return -EINPROGRESS on success and does
637 // not place the event in the given memory. We have to use
638 // io_getevents to wait for all the events we cancelled.
639 int ret = 0;
640 unsigned num_events = 0;
641 int save_errno = errno;
642 errno = 0;
643
644 for (unsigned j = start; j < end; j++) {
645 if (io_cancel(mCtx, iocb[j], nullptr) != -1 || errno != EINPROGRESS) {
646 PLOG(ERROR) << "Mtp couldn't cancel request " << j;
647 } else {
648 num_events++;
649 }
650 }
651 if (num_events != end - start) {
652 ret = -1;
653 errno = EIO;
654 }
655 int evs = TEMP_FAILURE_RETRY(io_getevents(mCtx, num_events, AIO_BUFS_MAX, events, nullptr));
656 if (static_cast<unsigned>(evs) != num_events) {
657 PLOG(ERROR) << "Mtp couldn't cancel all requests, got " << evs;
658 ret = -1;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700659 }
Jerry Zhang487be612016-10-24 12:10:41 -0700660
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700661 uint64_t ev_cnt = 0;
662 if (num_events && ::read(mEventFd, &ev_cnt, sizeof(ev_cnt)) == -1)
663 PLOG(ERROR) << "Mtp Unable to read event fd";
664
665 if (ret == 0) {
666 // Restore errno since it probably got overriden with EINPROGRESS.
667 errno = save_errno;
668 }
669 return ret;
670}
671
672int MtpFfsHandle::iobufSubmit(struct io_buffer *buf, int fd, unsigned length, bool read) {
673 int ret = 0;
674 buf->actual = AIO_BUFS_MAX;
675 for (unsigned j = 0; j < AIO_BUFS_MAX; j++) {
676 unsigned rq_length = std::min(AIO_BUF_LEN, length - AIO_BUF_LEN * j);
677 io_prep(buf->iocb[j], fd, buf->buf[j], rq_length, 0, read);
678 buf->iocb[j]->aio_flags |= IOCB_FLAG_RESFD;
679 buf->iocb[j]->aio_resfd = mEventFd;
680
681 // Not enough data, so table is truncated.
682 if (rq_length < AIO_BUF_LEN || length == AIO_BUF_LEN * (j + 1)) {
683 buf->actual = j + 1;
684 break;
685 }
686 }
687
688 ret = io_submit(mCtx, buf->actual, buf->iocb.data());
689 if (ret != static_cast<int>(buf->actual)) {
690 PLOG(ERROR) << "Mtp io_submit got " << ret << " expected " << buf->actual;
691 if (ret != -1) {
692 errno = EIO;
693 }
694 ret = -1;
695 }
696 return ret;
697}
698
699int MtpFfsHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
700 // When receiving files, the incoming length is given in 32 bits.
701 // A >=4G file is given as 0xFFFFFFFF
702 uint32_t file_length = mfr.length;
703 uint64_t offset = mfr.offset;
Jerry Zhang487be612016-10-24 12:10:41 -0700704
705 struct aiocb aio;
706 aio.aio_fildes = mfr.fd;
707 aio.aio_buf = nullptr;
708 struct aiocb *aiol[] = {&aio};
Jerry Zhang487be612016-10-24 12:10:41 -0700709
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700710 int ret = -1;
711 unsigned i = 0;
712 size_t length;
713 struct io_event ioevs[AIO_BUFS_MAX];
714 bool has_write = false;
715 bool error = false;
716 bool write_error = false;
717 int packet_size = getPacketSize(mBulkOut);
718 bool short_packet = false;
719 advise(mfr.fd);
Jerry Zhang487be612016-10-24 12:10:41 -0700720
721 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700722 while (file_length > 0 || has_write) {
723 // Queue an asynchronous read from USB.
Jerry Zhang487be612016-10-24 12:10:41 -0700724 if (file_length > 0) {
725 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700726 if (iobufSubmit(&mIobuf[i], mBulkOut, length, true) == -1)
727 error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700728 }
729
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700730 // Get the return status of the last write request.
731 if (has_write) {
Jerry Zhang487be612016-10-24 12:10:41 -0700732 aio_suspend(aiol, 1, nullptr);
Jerry Zhang487be612016-10-24 12:10:41 -0700733 int written = aio_return(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700734 if (static_cast<size_t>(written) < aio.aio_nbytes) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700735 errno = written == -1 ? aio_error(&aio) : EIO;
736 PLOG(ERROR) << "Mtp error writing to disk";
737 write_error = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700738 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700739 has_write = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700740 }
741
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700742 if (error) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700743 return -1;
744 }
745
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700746 // Get the result of the read request, and queue a write to disk.
747 if (file_length > 0) {
748 unsigned num_events = 0;
749 ret = 0;
750 unsigned short_i = mIobuf[i].actual;
751 while (num_events < short_i) {
752 // Get all events up to the short read, if there is one.
753 // We must wait for each event since data transfer could end at any time.
754 int this_events = 0;
755 int event_ret = waitEvents(&mIobuf[i], 1, ioevs, &this_events);
756 num_events += this_events;
757
758 if (event_ret == -1) {
759 cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual);
760 return -1;
761 }
762 ret += event_ret;
763 for (int j = 0; j < this_events; j++) {
764 // struct io_event contains a pointer to the associated struct iocb as a __u64.
765 if (static_cast<__u64>(ioevs[j].res) <
766 reinterpret_cast<struct iocb*>(ioevs[j].obj)->aio_nbytes) {
767 // We've found a short event. Store the index since
768 // events won't necessarily arrive in the order they are queued.
769 short_i = (ioevs[j].obj - reinterpret_cast<uint64_t>(mIobuf[i].iocbs.data()))
770 / sizeof(struct iocb) + 1;
771 short_packet = true;
772 }
773 }
774 }
775 if (short_packet) {
776 if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual)) {
777 write_error = true;
778 }
779 }
Jerry Zhang487be612016-10-24 12:10:41 -0700780 if (file_length == MAX_MTP_FILE_SIZE) {
781 // For larger files, receive until a short packet is received.
782 if (static_cast<size_t>(ret) < length) {
783 file_length = 0;
784 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700785 } else if (ret < static_cast<int>(length)) {
786 // If file is less than 4G and we get a short packet, it's an error.
787 errno = EIO;
788 LOG(ERROR) << "Mtp got unexpected short packet";
789 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700790 } else {
791 file_length -= ret;
792 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700793
794 if (write_error) {
795 cancelTransaction();
796 return -1;
797 }
798
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700799 // Enqueue a new write request
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700800 aio_prepare(&aio, mIobuf[i].bufs.data(), ret, offset);
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700801 aio_write(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700802
803 offset += ret;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700804 i = (i + 1) % NUM_IO_BUFS;
805 has_write = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700806 }
807 }
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700808 if ((ret % packet_size == 0 && !short_packet) || zero_packet) {
809 // Receive an empty packet if size is a multiple of the endpoint size
810 // and we didn't already get an empty packet from the header or large file.
811 if (read(mIobuf[0].bufs.data(), packet_size) != 0) {
Jerry Zhang54107562017-05-15 11:54:19 -0700812 return -1;
813 }
814 }
Jerry Zhang487be612016-10-24 12:10:41 -0700815 return 0;
816}
817
Jerry Zhang487be612016-10-24 12:10:41 -0700818int MtpFfsHandle::sendFile(mtp_file_range mfr) {
819 uint64_t file_length = mfr.length;
820 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
821 file_length + sizeof(mtp_data_header));
Jerry Zhang44180302017-02-03 16:31:31 -0800822 uint64_t offset = mfr.offset;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700823 int packet_size = getPacketSize(mBulkIn);
Jerry Zhang487be612016-10-24 12:10:41 -0700824
Jerry Zhang44180302017-02-03 16:31:31 -0800825 // If file_length is larger than a size_t, truncating would produce the wrong comparison.
826 // Instead, promote the left side to 64 bits, then truncate the small result.
827 int init_read_len = std::min(
828 static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700829
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700830 advise(mfr.fd);
Jerry Zhange9d94422017-01-18 12:03:56 -0800831
Jerry Zhang487be612016-10-24 12:10:41 -0700832 struct aiocb aio;
833 aio.aio_fildes = mfr.fd;
834 struct aiocb *aiol[] = {&aio};
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700835 int ret = 0;
836 int length, num_read;
837 unsigned i = 0;
838 struct io_event ioevs[AIO_BUFS_MAX];
839 bool error = false;
840 bool has_write = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700841
842 // Send the header data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700843 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(mIobuf[0].bufs.data());
844 header->length = htole32(given_length);
845 header->type = htole16(2); // data packet
846 header->command = htole16(mfr.command);
847 header->transaction_id = htole32(mfr.transaction_id);
Jerry Zhang487be612016-10-24 12:10:41 -0700848
849 // Some hosts don't support header/data separation even though MTP allows it
850 // Handle by filling first packet with initial file data
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700851 if (TEMP_FAILURE_RETRY(pread(mfr.fd, mIobuf[0].bufs.data() +
Jerry Zhang487be612016-10-24 12:10:41 -0700852 sizeof(mtp_data_header), init_read_len, offset))
853 != init_read_len) return -1;
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700854 if (write(mIobuf[0].bufs.data(), sizeof(mtp_data_header) + init_read_len) == -1)
855 return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700856 file_length -= init_read_len;
857 offset += init_read_len;
Jerry Zhang54107562017-05-15 11:54:19 -0700858 ret = init_read_len + sizeof(mtp_data_header);
Jerry Zhang487be612016-10-24 12:10:41 -0700859
Jerry Zhang487be612016-10-24 12:10:41 -0700860 // Break down the file into pieces that fit in buffers
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700861 while(file_length > 0 || has_write) {
862 if (file_length > 0) {
863 // Queue up a read from disk.
864 length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
865 aio_prepare(&aio, mIobuf[i].bufs.data(), length, offset);
866 aio_read(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700867 }
868
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700869 if (has_write) {
870 // Wait for usb write. Cancel unwritten portion if there's an error.
871 int num_events = 0;
872 if (waitEvents(&mIobuf[(i-1)%NUM_IO_BUFS], mIobuf[(i-1)%NUM_IO_BUFS].actual, ioevs,
873 &num_events) != ret) {
874 error = true;
875 cancelEvents(mIobuf[(i-1)%NUM_IO_BUFS].iocb.data(), ioevs, num_events,
876 mIobuf[(i-1)%NUM_IO_BUFS].actual);
877 }
878 has_write = false;
Jerry Zhang7063c932017-04-04 15:06:10 -0700879 }
880
Jerry Zhang487be612016-10-24 12:10:41 -0700881 if (file_length > 0) {
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700882 // Wait for the previous read to finish
883 aio_suspend(aiol, 1, nullptr);
884 num_read = aio_return(&aio);
885 if (static_cast<size_t>(num_read) < aio.aio_nbytes) {
886 errno = num_read == -1 ? aio_error(&aio) : EIO;
887 PLOG(ERROR) << "Mtp error reading from disk";
888 cancelTransaction();
889 return -1;
890 }
891
892 file_length -= num_read;
893 offset += num_read;
894
895 if (error) {
896 return -1;
897 }
898
899 // Queue up a write to usb.
900 if (iobufSubmit(&mIobuf[i], mBulkIn, num_read, false) == -1) {
901 return -1;
902 }
903 has_write = true;
904 ret = num_read;
Jerry Zhang487be612016-10-24 12:10:41 -0700905 }
906
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700907 i = (i + 1) % NUM_IO_BUFS;
Jerry Zhang487be612016-10-24 12:10:41 -0700908 }
909
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700910 if (ret % packet_size == 0) {
Jerry Zhang487be612016-10-24 12:10:41 -0700911 // If the last packet wasn't short, send a final empty packet
Jerry Zhangdf69dd32017-05-03 17:17:49 -0700912 if (write(mIobuf[0].bufs.data(), 0) != 0) {
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700913 return -1;
914 }
Jerry Zhang487be612016-10-24 12:10:41 -0700915 }
Jerry Zhang487be612016-10-24 12:10:41 -0700916 return 0;
917}
918
919int MtpFfsHandle::sendEvent(mtp_event me) {
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700920 // Mimic the behavior of f_mtp by sending the event async.
921 // Events aren't critical to the connection, so we don't need to check the return value.
922 char *temp = new char[me.length];
923 memcpy(temp, me.data, me.length);
924 me.data = temp;
Jerry Zhang008f4df2017-08-09 17:53:50 -0700925 std::thread t([this, me]() { return this->doSendEvent(me); });
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700926 t.detach();
927 return 0;
928}
929
930void MtpFfsHandle::doSendEvent(mtp_event me) {
Jerry Zhang487be612016-10-24 12:10:41 -0700931 unsigned length = me.length;
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700932 int ret = ::write(mIntr, me.data, length);
Jerry Zhang94ef0ea2017-07-26 11:37:23 -0700933 if (static_cast<unsigned>(ret) != length)
934 PLOG(ERROR) << "Mtp error sending event thread!";
Jerry Zhang008f4df2017-08-09 17:53:50 -0700935 delete[] reinterpret_cast<char*>(me.data);
Jerry Zhang487be612016-10-24 12:10:41 -0700936}
937
938} // namespace android
939