blob: 9139925a8e5d1b15f5421a554ac5f84a2ae0afbc [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>
19#include <dirent.h>
20#include <errno.h>
21#include <fcntl.h>
22#include <linux/usb/ch9.h>
23#include <linux/usb/functionfs.h>
24#include <mutex>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <sys/endian.h>
29#include <sys/ioctl.h>
Jerry Zhange9d94422017-01-18 12:03:56 -080030#include <sys/mman.h>
Jerry Zhang487be612016-10-24 12:10:41 -070031#include <sys/stat.h>
32#include <sys/types.h>
33#include <unistd.h>
34#include <vector>
35
36#include "AsyncIO.h"
37#include "MtpFfsHandle.h"
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -080038#include "mtp.h"
Jerry Zhang487be612016-10-24 12:10:41 -070039
40#define cpu_to_le16(x) htole16(x)
41#define cpu_to_le32(x) htole32(x)
42
Jerry Zhang94b13222017-02-09 11:02:49 -080043#define FUNCTIONFS_ENDPOINT_ALLOC _IOR('g', 231, __u32)
Jerry Zhang5a804b92016-12-15 17:07:38 -080044
Jerry Zhang487be612016-10-24 12:10:41 -070045namespace {
46
47constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
48constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
49constexpr char FFS_MTP_EP_INTR[] = "/dev/usb-ffs/mtp/ep3";
50
51constexpr int MAX_PACKET_SIZE_FS = 64;
52constexpr int MAX_PACKET_SIZE_HS = 512;
53constexpr int MAX_PACKET_SIZE_SS = 1024;
54
55// Must be divisible by all max packet size values
56constexpr int MAX_FILE_CHUNK_SIZE = 3145728;
57
58// Safe values since some devices cannot handle large DMAs
59// To get good performance, override these with
60// higher values per device using the properties
61// sys.usb.ffs.max_read and sys.usb.ffs.max_write
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -080062constexpr int USB_FFS_MAX_WRITE = MTP_BUFFER_SIZE;
63constexpr int USB_FFS_MAX_READ = MTP_BUFFER_SIZE;
Jerry Zhang487be612016-10-24 12:10:41 -070064
Jerry Zhangdfb8b162017-09-07 11:34:25 -070065constexpr unsigned FFS_NUM_EVENTS = 5;
66
Jerry Zhangb4f54262017-02-02 18:14:33 -080067static_assert(USB_FFS_MAX_WRITE > 0, "Max r/w values must be > 0!");
68static_assert(USB_FFS_MAX_READ > 0, "Max r/w values must be > 0!");
69
Jerry Zhang487be612016-10-24 12:10:41 -070070constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
71
Jerry Zhangb4f54262017-02-02 18:14:33 -080072constexpr size_t ENDPOINT_ALLOC_RETRIES = 10;
73
Jerry Zhang487be612016-10-24 12:10:41 -070074struct func_desc {
75 struct usb_interface_descriptor intf;
76 struct usb_endpoint_descriptor_no_audio sink;
77 struct usb_endpoint_descriptor_no_audio source;
78 struct usb_endpoint_descriptor_no_audio intr;
79} __attribute__((packed));
80
81struct ss_func_desc {
82 struct usb_interface_descriptor intf;
83 struct usb_endpoint_descriptor_no_audio sink;
84 struct usb_ss_ep_comp_descriptor sink_comp;
85 struct usb_endpoint_descriptor_no_audio source;
86 struct usb_ss_ep_comp_descriptor source_comp;
87 struct usb_endpoint_descriptor_no_audio intr;
88 struct usb_ss_ep_comp_descriptor intr_comp;
89} __attribute__((packed));
90
91struct desc_v1 {
92 struct usb_functionfs_descs_head_v1 {
93 __le32 magic;
94 __le32 length;
95 __le32 fs_count;
96 __le32 hs_count;
97 } __attribute__((packed)) header;
98 struct func_desc fs_descs, hs_descs;
99} __attribute__((packed));
100
101struct desc_v2 {
102 struct usb_functionfs_descs_head_v2 header;
103 // The rest of the structure depends on the flags in the header.
104 __le32 fs_count;
105 __le32 hs_count;
106 __le32 ss_count;
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700107 __le32 os_count;
Jerry Zhang487be612016-10-24 12:10:41 -0700108 struct func_desc fs_descs, hs_descs;
109 struct ss_func_desc ss_descs;
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700110 struct usb_os_desc_header os_header;
111 struct usb_ext_compat_desc os_desc;
Jerry Zhang487be612016-10-24 12:10:41 -0700112} __attribute__((packed));
113
114const struct usb_interface_descriptor mtp_interface_desc = {
115 .bLength = USB_DT_INTERFACE_SIZE,
116 .bDescriptorType = USB_DT_INTERFACE,
117 .bInterfaceNumber = 0,
118 .bNumEndpoints = 3,
119 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
120 .bInterfaceSubClass = 1,
121 .bInterfaceProtocol = 1,
Jerry Zhang6a790522017-01-11 15:17:53 -0800122 .iInterface = 1,
Jerry Zhang487be612016-10-24 12:10:41 -0700123};
124
125const struct usb_interface_descriptor ptp_interface_desc = {
126 .bLength = USB_DT_INTERFACE_SIZE,
127 .bDescriptorType = USB_DT_INTERFACE,
128 .bInterfaceNumber = 0,
129 .bNumEndpoints = 3,
130 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
131 .bInterfaceSubClass = 1,
132 .bInterfaceProtocol = 1,
133};
134
135const struct usb_endpoint_descriptor_no_audio fs_sink = {
136 .bLength = USB_DT_ENDPOINT_SIZE,
137 .bDescriptorType = USB_DT_ENDPOINT,
138 .bEndpointAddress = 1 | USB_DIR_IN,
139 .bmAttributes = USB_ENDPOINT_XFER_BULK,
140 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
141};
142
143const struct usb_endpoint_descriptor_no_audio fs_source = {
144 .bLength = USB_DT_ENDPOINT_SIZE,
145 .bDescriptorType = USB_DT_ENDPOINT,
146 .bEndpointAddress = 2 | USB_DIR_OUT,
147 .bmAttributes = USB_ENDPOINT_XFER_BULK,
148 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
149};
150
151const struct usb_endpoint_descriptor_no_audio fs_intr = {
152 .bLength = USB_DT_ENDPOINT_SIZE,
153 .bDescriptorType = USB_DT_ENDPOINT,
154 .bEndpointAddress = 3 | USB_DIR_IN,
155 .bmAttributes = USB_ENDPOINT_XFER_INT,
156 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
157 .bInterval = 6,
158};
159
160const struct usb_endpoint_descriptor_no_audio hs_sink = {
161 .bLength = USB_DT_ENDPOINT_SIZE,
162 .bDescriptorType = USB_DT_ENDPOINT,
163 .bEndpointAddress = 1 | USB_DIR_IN,
164 .bmAttributes = USB_ENDPOINT_XFER_BULK,
165 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
166};
167
168const struct usb_endpoint_descriptor_no_audio hs_source = {
169 .bLength = USB_DT_ENDPOINT_SIZE,
170 .bDescriptorType = USB_DT_ENDPOINT,
171 .bEndpointAddress = 2 | USB_DIR_OUT,
172 .bmAttributes = USB_ENDPOINT_XFER_BULK,
173 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
174};
175
176const struct usb_endpoint_descriptor_no_audio hs_intr = {
177 .bLength = USB_DT_ENDPOINT_SIZE,
178 .bDescriptorType = USB_DT_ENDPOINT,
179 .bEndpointAddress = 3 | USB_DIR_IN,
180 .bmAttributes = USB_ENDPOINT_XFER_INT,
181 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
182 .bInterval = 6,
183};
184
185const struct usb_endpoint_descriptor_no_audio ss_sink = {
186 .bLength = USB_DT_ENDPOINT_SIZE,
187 .bDescriptorType = USB_DT_ENDPOINT,
188 .bEndpointAddress = 1 | USB_DIR_IN,
189 .bmAttributes = USB_ENDPOINT_XFER_BULK,
190 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
191};
192
193const struct usb_endpoint_descriptor_no_audio ss_source = {
194 .bLength = USB_DT_ENDPOINT_SIZE,
195 .bDescriptorType = USB_DT_ENDPOINT,
196 .bEndpointAddress = 2 | USB_DIR_OUT,
197 .bmAttributes = USB_ENDPOINT_XFER_BULK,
198 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
199};
200
201const struct usb_endpoint_descriptor_no_audio ss_intr = {
202 .bLength = USB_DT_ENDPOINT_SIZE,
203 .bDescriptorType = USB_DT_ENDPOINT,
204 .bEndpointAddress = 3 | USB_DIR_IN,
205 .bmAttributes = USB_ENDPOINT_XFER_INT,
206 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
207 .bInterval = 6,
208};
209
210const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
211 .bLength = sizeof(ss_sink_comp),
212 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800213 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700214};
215
216const struct usb_ss_ep_comp_descriptor ss_source_comp = {
217 .bLength = sizeof(ss_source_comp),
218 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800219 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700220};
221
222const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
223 .bLength = sizeof(ss_intr_comp),
224 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
225};
226
227const struct func_desc mtp_fs_descriptors = {
228 .intf = mtp_interface_desc,
229 .sink = fs_sink,
230 .source = fs_source,
231 .intr = fs_intr,
232};
233
234const struct func_desc mtp_hs_descriptors = {
235 .intf = mtp_interface_desc,
236 .sink = hs_sink,
237 .source = hs_source,
238 .intr = hs_intr,
239};
240
241const struct ss_func_desc mtp_ss_descriptors = {
242 .intf = mtp_interface_desc,
243 .sink = ss_sink,
244 .sink_comp = ss_sink_comp,
245 .source = ss_source,
246 .source_comp = ss_source_comp,
247 .intr = ss_intr,
248 .intr_comp = ss_intr_comp,
249};
250
251const struct func_desc ptp_fs_descriptors = {
252 .intf = ptp_interface_desc,
253 .sink = fs_sink,
254 .source = fs_source,
255 .intr = fs_intr,
256};
257
258const struct func_desc ptp_hs_descriptors = {
259 .intf = ptp_interface_desc,
260 .sink = hs_sink,
261 .source = hs_source,
262 .intr = hs_intr,
263};
264
265const struct ss_func_desc ptp_ss_descriptors = {
266 .intf = ptp_interface_desc,
267 .sink = ss_sink,
268 .sink_comp = ss_sink_comp,
269 .source = ss_source,
270 .source_comp = ss_source_comp,
271 .intr = ss_intr,
272 .intr_comp = ss_intr_comp,
273};
274
Jerry Zhang6a790522017-01-11 15:17:53 -0800275#define STR_INTERFACE "MTP"
Jerry Zhang487be612016-10-24 12:10:41 -0700276const struct {
277 struct usb_functionfs_strings_head header;
Jerry Zhang6a790522017-01-11 15:17:53 -0800278 struct {
279 __le16 code;
280 const char str1[sizeof(STR_INTERFACE)];
281 } __attribute__((packed)) lang0;
Jerry Zhang487be612016-10-24 12:10:41 -0700282} __attribute__((packed)) strings = {
283 .header = {
284 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
285 .length = cpu_to_le32(sizeof(strings)),
Jerry Zhang6a790522017-01-11 15:17:53 -0800286 .str_count = cpu_to_le32(1),
287 .lang_count = cpu_to_le32(1),
288 },
289 .lang0 = {
290 .code = cpu_to_le16(0x0409),
291 .str1 = STR_INTERFACE,
Jerry Zhang487be612016-10-24 12:10:41 -0700292 },
293};
294
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700295struct usb_os_desc_header mtp_os_desc_header = {
296 .interface = htole32(1),
297 .dwLength = htole32(sizeof(usb_os_desc_header) + sizeof(usb_ext_compat_desc)),
298 .bcdVersion = htole16(1),
299 .wIndex = htole16(4),
300 .bCount = htole16(1),
301 .Reserved = htole16(0),
302};
303
304struct usb_ext_compat_desc mtp_os_desc_compat = {
305 .bFirstInterfaceNumber = 0,
306 .Reserved1 = htole32(1),
307 .CompatibleID = { 'M', 'T', 'P' },
308 .SubCompatibleID = {0},
309 .Reserved2 = {0},
310};
311
312struct usb_ext_compat_desc ptp_os_desc_compat = {
313 .bFirstInterfaceNumber = 0,
314 .Reserved1 = htole32(1),
315 .CompatibleID = { 'P', 'T', 'P' },
316 .SubCompatibleID = {0},
317 .Reserved2 = {0},
318};
319
Jerry Zhangdfb8b162017-09-07 11:34:25 -0700320struct mtp_device_status {
321 uint16_t wLength;
322 uint16_t wCode;
323};
324
Jerry Zhang487be612016-10-24 12:10:41 -0700325} // anonymous namespace
326
327namespace android {
328
329MtpFfsHandle::MtpFfsHandle() :
330 mMaxWrite(USB_FFS_MAX_WRITE),
331 mMaxRead(USB_FFS_MAX_READ) {}
332
333MtpFfsHandle::~MtpFfsHandle() {}
334
335void MtpFfsHandle::closeEndpoints() {
336 mIntr.reset();
337 mBulkIn.reset();
338 mBulkOut.reset();
339}
340
341bool MtpFfsHandle::initFunctionfs() {
342 ssize_t ret;
343 struct desc_v1 v1_descriptor;
344 struct desc_v2 v2_descriptor;
345
346 v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
347 v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
348 v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700349 FUNCTIONFS_HAS_SS_DESC | FUNCTIONFS_HAS_MS_OS_DESC;
Jerry Zhang487be612016-10-24 12:10:41 -0700350 v2_descriptor.fs_count = 4;
351 v2_descriptor.hs_count = 4;
352 v2_descriptor.ss_count = 7;
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700353 v2_descriptor.os_count = 1;
Jerry Zhang487be612016-10-24 12:10:41 -0700354 v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
355 v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
356 v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
Jerry Zhang4d7ccef2017-08-31 11:57:45 -0700357 v2_descriptor.os_header = mtp_os_desc_header;
358 v2_descriptor.os_desc = mPtp ? ptp_os_desc_compat : mtp_os_desc_compat;
Jerry Zhang487be612016-10-24 12:10:41 -0700359
360 if (mControl < 0) { // might have already done this before
361 mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
362 if (mControl < 0) {
363 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
364 goto err;
365 }
366
367 ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
368 if (ret < 0) {
369 v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
370 v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
371 v1_descriptor.header.fs_count = 4;
372 v1_descriptor.header.hs_count = 4;
373 v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
374 v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
375 PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
376 ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
377 if (ret < 0) {
378 PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
379 goto err;
380 }
381 }
382 ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
383 if (ret < 0) {
384 PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
385 goto err;
386 }
387 }
388 if (mBulkIn > -1 || mBulkOut > -1 || mIntr > -1)
389 LOG(WARNING) << "Endpoints were not closed before configure!";
390
Jerry Zhang487be612016-10-24 12:10:41 -0700391 return true;
392
393err:
Jerry Zhang487be612016-10-24 12:10:41 -0700394 closeConfig();
395 return false;
396}
397
398void MtpFfsHandle::closeConfig() {
399 mControl.reset();
400}
401
Jerry Zhangdfb8b162017-09-07 11:34:25 -0700402void MtpFfsHandle::controlLoop() {
403 while (!handleEvent()) {}
404 LOG(DEBUG) << "Mtp server shutting down";
405}
406
407int MtpFfsHandle::handleEvent() {
408 std::vector<usb_functionfs_event> events(FFS_NUM_EVENTS);
409 usb_functionfs_event *event = events.data();
410 int nbytes = TEMP_FAILURE_RETRY(::read(mControl, event,
411 events.size() * sizeof(usb_functionfs_event)));
412 if (nbytes == -1) {
413 return -1;
414 }
415 int ret = 0;
416 for (size_t n = nbytes / sizeof *event; n; --n, ++event) {
417 switch (event->type) {
418 case FUNCTIONFS_BIND:
419 case FUNCTIONFS_ENABLE:
420 case FUNCTIONFS_RESUME:
421 ret = 0;
422 errno = 0;
423 break;
424 case FUNCTIONFS_SUSPEND:
425 case FUNCTIONFS_UNBIND:
426 case FUNCTIONFS_DISABLE:
427 errno = ESHUTDOWN;
428 ret = -1;
429 break;
430 case FUNCTIONFS_SETUP:
431 if (handleControlRequest(&event->u.setup) == -1)
432 ret = -1;
433 break;
434 default:
435 LOG(DEBUG) << "Mtp Event " << event->type << " (unknown)";
436 }
437 }
438 return ret;
439}
440
441int MtpFfsHandle::handleControlRequest(const struct usb_ctrlrequest *setup) {
442 uint8_t type = setup->bRequestType;
443 uint8_t code = setup->bRequest;
444 uint16_t length = setup->wLength;
445 uint16_t index = setup->wIndex;
446 uint16_t value = setup->wValue;
447 std::vector<char> buf;
448 buf.resize(length);
449
450 if (!(type & USB_DIR_IN)) {
451 if (::read(mControl, buf.data(), length) != length) {
452 PLOG(DEBUG) << "Mtp error ctrlreq read data";
453 }
454 }
455
456 if ((type & USB_TYPE_MASK) == USB_TYPE_CLASS && index == 0 && value == 0) {
457 switch(code) {
458 case MTP_REQ_GET_DEVICE_STATUS:
459 {
460 if (length < sizeof(struct mtp_device_status)) {
461 return -1;
462 }
463 struct mtp_device_status *st = reinterpret_cast<struct mtp_device_status*>(buf.data());
464 st->wLength = htole16(sizeof(st));
465 st->wCode = MTP_RESPONSE_OK;
466 length = st->wLength;
467 break;
468 }
469 default:
470 LOG(DEBUG) << "Unrecognized Mtp class request! " << code;
471 }
472 } else {
473 LOG(DEBUG) << "Unrecognized request type " << type;
474 }
475
476 if (type & USB_DIR_IN) {
477 if (::write(mControl, buf.data(), length) != length) {
478 PLOG(DEBUG) << "Mtp error ctrlreq write data";
479 }
480 }
481 return 0;
482}
483
Jerry Zhang487be612016-10-24 12:10:41 -0700484int MtpFfsHandle::writeHandle(int fd, const void* data, int len) {
485 LOG(VERBOSE) << "MTP about to write fd = " << fd << ", len=" << len;
486 int ret = 0;
487 const char* buf = static_cast<const char*>(data);
488 while (len > 0) {
489 int write_len = std::min(mMaxWrite, len);
490 int n = TEMP_FAILURE_RETRY(::write(fd, buf, write_len));
491
492 if (n < 0) {
493 PLOG(ERROR) << "write ERROR: fd = " << fd << ", n = " << n;
494 return -1;
495 } else if (n < write_len) {
496 errno = EIO;
497 PLOG(ERROR) << "less written than expected";
498 return -1;
499 }
500 buf += n;
501 len -= n;
502 ret += n;
503 }
504 return ret;
505}
506
507int MtpFfsHandle::readHandle(int fd, void* data, int len) {
508 LOG(VERBOSE) << "MTP about to read fd = " << fd << ", len=" << len;
509 int ret = 0;
510 char* buf = static_cast<char*>(data);
511 while (len > 0) {
512 int read_len = std::min(mMaxRead, len);
513 int n = TEMP_FAILURE_RETRY(::read(fd, buf, read_len));
514 if (n < 0) {
515 PLOG(ERROR) << "read ERROR: fd = " << fd << ", n = " << n;
516 return -1;
517 }
518 ret += n;
519 if (n < read_len) // done reading early
520 break;
521 buf += n;
522 len -= n;
523 }
524 return ret;
525}
526
527int MtpFfsHandle::spliceReadHandle(int fd, int pipe_out, int len) {
528 LOG(VERBOSE) << "MTP about to splice read fd = " << fd << ", len=" << len;
529 int ret = 0;
530 loff_t dummyoff;
531 while (len > 0) {
532 int read_len = std::min(mMaxRead, len);
533 dummyoff = 0;
534 int n = TEMP_FAILURE_RETRY(splice(fd, &dummyoff, pipe_out, nullptr, read_len, 0));
535 if (n < 0) {
536 PLOG(ERROR) << "splice read ERROR: fd = " << fd << ", n = " << n;
537 return -1;
538 }
539 ret += n;
540 if (n < read_len) // done reading early
541 break;
542 len -= n;
543 }
544 return ret;
545}
546
547int MtpFfsHandle::read(void* data, int len) {
548 return readHandle(mBulkOut, data, len);
549}
550
551int MtpFfsHandle::write(const void* data, int len) {
552 return writeHandle(mBulkIn, data, len);
553}
554
555int MtpFfsHandle::start() {
556 mLock.lock();
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800557
558 mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
559 if (mBulkIn < 0) {
560 PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
561 return -1;
562 }
563
564 mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
565 if (mBulkOut < 0) {
566 PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
567 return -1;
568 }
569
570 mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
571 if (mIntr < 0) {
572 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
573 return -1;
574 }
575
576 mBuffer1.resize(MAX_FILE_CHUNK_SIZE);
577 mBuffer2.resize(MAX_FILE_CHUNK_SIZE);
578 posix_madvise(mBuffer1.data(), MAX_FILE_CHUNK_SIZE,
579 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
580 posix_madvise(mBuffer2.data(), MAX_FILE_CHUNK_SIZE,
581 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
582
Jerry Zhangdfb8b162017-09-07 11:34:25 -0700583 // Handle control requests.
584 std::thread t([this]() { this->controlLoop(); });
585 t.detach();
586
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800587 // Get device specific r/w size
588 mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
589 mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);
590
Jerry Zhangb4f54262017-02-02 18:14:33 -0800591 size_t attempts = 0;
592 while (mMaxWrite >= USB_FFS_MAX_WRITE && mMaxRead >= USB_FFS_MAX_READ &&
593 attempts < ENDPOINT_ALLOC_RETRIES) {
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800594 // If larger contiguous chunks of memory aren't available, attempt to try
595 // smaller allocations.
596 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) ||
597 ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) {
Jerry Zhangb4f54262017-02-02 18:14:33 -0800598 if (errno == ENODEV) {
599 // Driver hasn't enabled endpoints yet.
600 std::this_thread::sleep_for(std::chrono::milliseconds(100));
601 attempts += 1;
602 continue;
603 }
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800604 mMaxWrite /= 2;
605 mMaxRead /=2;
606 } else {
607 return 0;
608 }
609 }
Jerry Zhangb4f54262017-02-02 18:14:33 -0800610 // Try to start MtpServer anyway, with the smallest max r/w values
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800611 PLOG(ERROR) << "Functionfs could not allocate any memory!";
Jerry Zhangb4f54262017-02-02 18:14:33 -0800612 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700613}
614
615int MtpFfsHandle::configure(bool usePtp) {
616 // Wait till previous server invocation has closed
Jerry Zhang9dc10032017-10-23 12:03:40 -0700617 if (!mLock.try_lock_for(std::chrono::milliseconds(300))) {
Jerry Zhang0475d912017-04-03 11:24:48 -0700618 LOG(ERROR) << "MtpServer was unable to get configure lock";
619 return -1;
620 }
621 int ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700622
623 // If ptp is changed, the configuration must be rewritten
624 if (mPtp != usePtp) {
625 closeEndpoints();
626 closeConfig();
627 }
628 mPtp = usePtp;
629
630 if (!initFunctionfs()) {
Jerry Zhang0475d912017-04-03 11:24:48 -0700631 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700632 }
Jerry Zhang0475d912017-04-03 11:24:48 -0700633 mLock.unlock();
634 return ret;
Jerry Zhang487be612016-10-24 12:10:41 -0700635}
636
637void MtpFfsHandle::close() {
638 closeEndpoints();
639 mLock.unlock();
640}
641
642/* Read from USB and write to a local file. */
Jerry Zhang54107562017-05-15 11:54:19 -0700643int MtpFfsHandle::receiveFile(mtp_file_range mfr, bool zero_packet) {
Jerry Zhang487be612016-10-24 12:10:41 -0700644 // When receiving files, the incoming length is given in 32 bits.
645 // A >4G file is given as 0xFFFFFFFF
646 uint32_t file_length = mfr.length;
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700647 uint64_t offset = mfr.offset;
648 struct usb_endpoint_descriptor mBulkOut_desc;
649 int packet_size;
650
651 if (ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkOut_desc))) {
652 PLOG(ERROR) << "Could not get FFS bulk-out descriptor";
653 packet_size = MAX_PACKET_SIZE_HS;
654 } else {
655 packet_size = mBulkOut_desc.wMaxPacketSize;
656 }
Jerry Zhang487be612016-10-24 12:10:41 -0700657
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800658 char *data = mBuffer1.data();
659 char *data2 = mBuffer2.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700660
661 struct aiocb aio;
662 aio.aio_fildes = mfr.fd;
663 aio.aio_buf = nullptr;
664 struct aiocb *aiol[] = {&aio};
Jerry Zhang54107562017-05-15 11:54:19 -0700665 int ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700666 size_t length;
667 bool read = false;
668 bool write = false;
Jerry Zhang5e6df682017-09-07 16:09:59 -0700669 bool short_packet = false;
Jerry Zhang487be612016-10-24 12:10:41 -0700670
671 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
672
673 // Break down the file into pieces that fit in buffers
674 while (file_length > 0 || write) {
675 if (file_length > 0) {
676 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
677
Jerry Zhang7063c932017-04-04 15:06:10 -0700678 // Read data from USB, handle errors after waiting for write thread.
679 ret = readHandle(mBulkOut, data, length);
Jerry Zhang487be612016-10-24 12:10:41 -0700680
681 if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700682 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700683 errno = EIO;
Jerry Zhang487be612016-10-24 12:10:41 -0700684 }
685 read = true;
686 }
687
688 if (write) {
689 // get the return status of the last write request
690 aio_suspend(aiol, 1, nullptr);
691
692 int written = aio_return(&aio);
693 if (written == -1) {
694 errno = aio_error(&aio);
695 return -1;
696 }
697 if (static_cast<size_t>(written) < aio.aio_nbytes) {
698 errno = EIO;
699 return -1;
700 }
701 write = false;
702 }
703
Jerry Zhang7063c932017-04-04 15:06:10 -0700704 // If there was an error reading above
705 if (ret == -1) {
706 return -1;
707 }
708
Jerry Zhang487be612016-10-24 12:10:41 -0700709 if (read) {
Jerry Zhang487be612016-10-24 12:10:41 -0700710 if (file_length == MAX_MTP_FILE_SIZE) {
711 // For larger files, receive until a short packet is received.
712 if (static_cast<size_t>(ret) < length) {
713 file_length = 0;
Jerry Zhang5e6df682017-09-07 16:09:59 -0700714 short_packet = true;
Jerry Zhang487be612016-10-24 12:10:41 -0700715 }
716 } else {
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700717 // Receive an empty packet if size is a multiple of the endpoint size.
Jerry Zhang487be612016-10-24 12:10:41 -0700718 file_length -= ret;
719 }
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700720 // Enqueue a new write request
721 aio.aio_buf = data;
722 aio.aio_sink = mfr.fd;
723 aio.aio_offset = offset;
724 aio.aio_nbytes = ret;
725 aio_write(&aio);
Jerry Zhang487be612016-10-24 12:10:41 -0700726
727 offset += ret;
728 std::swap(data, data2);
729
730 write = true;
731 read = false;
732 }
733 }
Jerry Zhang5e6df682017-09-07 16:09:59 -0700734 if ((ret % packet_size == 0 && !short_packet) || zero_packet) {
Jerry Zhang54107562017-05-15 11:54:19 -0700735 if (TEMP_FAILURE_RETRY(::read(mBulkOut, data, packet_size)) != 0) {
736 return -1;
737 }
738 }
Jerry Zhang487be612016-10-24 12:10:41 -0700739 return 0;
740}
741
742/* Read from a local file and send over USB. */
743int MtpFfsHandle::sendFile(mtp_file_range mfr) {
744 uint64_t file_length = mfr.length;
745 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
746 file_length + sizeof(mtp_data_header));
Jerry Zhang44180302017-02-03 16:31:31 -0800747 uint64_t offset = mfr.offset;
Jerry Zhang487be612016-10-24 12:10:41 -0700748 struct usb_endpoint_descriptor mBulkIn_desc;
749 int packet_size;
750
751 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkIn_desc))) {
752 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
753 packet_size = MAX_PACKET_SIZE_HS;
754 } else {
755 packet_size = mBulkIn_desc.wMaxPacketSize;
756 }
757
Jerry Zhang44180302017-02-03 16:31:31 -0800758 // If file_length is larger than a size_t, truncating would produce the wrong comparison.
759 // Instead, promote the left side to 64 bits, then truncate the small result.
760 int init_read_len = std::min(
761 static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700762
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800763 char *data = mBuffer1.data();
764 char *data2 = mBuffer2.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700765
Jerry Zhange9d94422017-01-18 12:03:56 -0800766 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
Jerry Zhange9d94422017-01-18 12:03:56 -0800767
Jerry Zhang487be612016-10-24 12:10:41 -0700768 struct aiocb aio;
769 aio.aio_fildes = mfr.fd;
770 struct aiocb *aiol[] = {&aio};
771 int ret, length;
Jerry Zhang7063c932017-04-04 15:06:10 -0700772 int error = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700773 bool read = false;
774 bool write = false;
775
776 // Send the header data
777 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(data);
778 header->length = __cpu_to_le32(given_length);
779 header->type = __cpu_to_le16(2); /* data packet */
780 header->command = __cpu_to_le16(mfr.command);
781 header->transaction_id = __cpu_to_le32(mfr.transaction_id);
782
783 // Some hosts don't support header/data separation even though MTP allows it
784 // Handle by filling first packet with initial file data
785 if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
786 sizeof(mtp_data_header), init_read_len, offset))
787 != init_read_len) return -1;
Jerry Zhang44180302017-02-03 16:31:31 -0800788 if (writeHandle(mBulkIn, data, sizeof(mtp_data_header) + init_read_len) == -1) return -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700789 file_length -= init_read_len;
790 offset += init_read_len;
Jerry Zhang54107562017-05-15 11:54:19 -0700791 ret = init_read_len + sizeof(mtp_data_header);
Jerry Zhang487be612016-10-24 12:10:41 -0700792
Jerry Zhang487be612016-10-24 12:10:41 -0700793 // Break down the file into pieces that fit in buffers
794 while(file_length > 0) {
795 if (read) {
796 // Wait for the previous read to finish
797 aio_suspend(aiol, 1, nullptr);
798 ret = aio_return(&aio);
799 if (ret == -1) {
800 errno = aio_error(&aio);
801 return -1;
802 }
803 if (static_cast<size_t>(ret) < aio.aio_nbytes) {
804 errno = EIO;
805 return -1;
806 }
807
808 file_length -= ret;
809 offset += ret;
810 std::swap(data, data2);
811 read = false;
812 write = true;
813 }
814
Jerry Zhang7063c932017-04-04 15:06:10 -0700815 if (error == -1) {
816 return -1;
817 }
818
Jerry Zhang487be612016-10-24 12:10:41 -0700819 if (file_length > 0) {
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800820 length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700821 // Queue up another read
822 aio.aio_buf = data;
823 aio.aio_offset = offset;
824 aio.aio_nbytes = length;
825 aio_read(&aio);
826 read = true;
827 }
828
829 if (write) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700830 if (writeHandle(mBulkIn, data2, ret) == -1) {
831 error = -1;
832 }
Jerry Zhang487be612016-10-24 12:10:41 -0700833 write = false;
834 }
835 }
836
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700837 if (ret % packet_size == 0) {
Jerry Zhang487be612016-10-24 12:10:41 -0700838 // If the last packet wasn't short, send a final empty packet
Jerry Zhangc9cbf982017-04-14 15:26:53 -0700839 if (TEMP_FAILURE_RETRY(::write(mBulkIn, data, 0)) != 0) {
840 return -1;
841 }
Jerry Zhang487be612016-10-24 12:10:41 -0700842 }
843
844 return 0;
845}
846
847int MtpFfsHandle::sendEvent(mtp_event me) {
Jerry Zhangd80492b2017-07-26 11:37:23 -0700848 // Mimic the behavior of f_mtp by sending the event async.
849 // Events aren't critical to the connection, so we don't need to check the return value.
850 char *temp = new char[me.length];
851 memcpy(temp, me.data, me.length);
852 me.data = temp;
Jerry Zhang73603032017-08-09 17:53:50 -0700853 std::thread t([this, me]() { return this->doSendEvent(me); });
Jerry Zhangd80492b2017-07-26 11:37:23 -0700854 t.detach();
855 return 0;
856}
857
858void MtpFfsHandle::doSendEvent(mtp_event me) {
Jerry Zhang487be612016-10-24 12:10:41 -0700859 unsigned length = me.length;
Jerry Zhangd80492b2017-07-26 11:37:23 -0700860 int ret = ::write(mIntr, me.data, length);
Jerry Zhangd80492b2017-07-26 11:37:23 -0700861 if (static_cast<unsigned>(ret) != length)
862 PLOG(ERROR) << "Mtp error sending event thread!";
Jerry Zhang73603032017-08-09 17:53:50 -0700863 delete[] reinterpret_cast<char*>(me.data);
Jerry Zhang487be612016-10-24 12:10:41 -0700864}
865
866} // namespace android
867
868IMtpHandle *get_ffs_handle() {
869 return new android::MtpFfsHandle();
870}
871