blob: 565a2fefe0855e662d081c2968ba74f23920077c [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 Zhangb4f54262017-02-02 18:14:33 -080065static_assert(USB_FFS_MAX_WRITE > 0, "Max r/w values must be > 0!");
66static_assert(USB_FFS_MAX_READ > 0, "Max r/w values must be > 0!");
67
Jerry Zhang487be612016-10-24 12:10:41 -070068constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
69
Jerry Zhangb4f54262017-02-02 18:14:33 -080070constexpr size_t ENDPOINT_ALLOC_RETRIES = 10;
71
Jerry Zhang487be612016-10-24 12:10:41 -070072struct func_desc {
73 struct usb_interface_descriptor intf;
74 struct usb_endpoint_descriptor_no_audio sink;
75 struct usb_endpoint_descriptor_no_audio source;
76 struct usb_endpoint_descriptor_no_audio intr;
77} __attribute__((packed));
78
79struct ss_func_desc {
80 struct usb_interface_descriptor intf;
81 struct usb_endpoint_descriptor_no_audio sink;
82 struct usb_ss_ep_comp_descriptor sink_comp;
83 struct usb_endpoint_descriptor_no_audio source;
84 struct usb_ss_ep_comp_descriptor source_comp;
85 struct usb_endpoint_descriptor_no_audio intr;
86 struct usb_ss_ep_comp_descriptor intr_comp;
87} __attribute__((packed));
88
89struct desc_v1 {
90 struct usb_functionfs_descs_head_v1 {
91 __le32 magic;
92 __le32 length;
93 __le32 fs_count;
94 __le32 hs_count;
95 } __attribute__((packed)) header;
96 struct func_desc fs_descs, hs_descs;
97} __attribute__((packed));
98
99struct desc_v2 {
100 struct usb_functionfs_descs_head_v2 header;
101 // The rest of the structure depends on the flags in the header.
102 __le32 fs_count;
103 __le32 hs_count;
104 __le32 ss_count;
105 struct func_desc fs_descs, hs_descs;
106 struct ss_func_desc ss_descs;
107} __attribute__((packed));
108
109const struct usb_interface_descriptor mtp_interface_desc = {
110 .bLength = USB_DT_INTERFACE_SIZE,
111 .bDescriptorType = USB_DT_INTERFACE,
112 .bInterfaceNumber = 0,
113 .bNumEndpoints = 3,
114 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
115 .bInterfaceSubClass = 1,
116 .bInterfaceProtocol = 1,
Jerry Zhang6a790522017-01-11 15:17:53 -0800117 .iInterface = 1,
Jerry Zhang487be612016-10-24 12:10:41 -0700118};
119
120const struct usb_interface_descriptor ptp_interface_desc = {
121 .bLength = USB_DT_INTERFACE_SIZE,
122 .bDescriptorType = USB_DT_INTERFACE,
123 .bInterfaceNumber = 0,
124 .bNumEndpoints = 3,
125 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
126 .bInterfaceSubClass = 1,
127 .bInterfaceProtocol = 1,
128};
129
130const struct usb_endpoint_descriptor_no_audio fs_sink = {
131 .bLength = USB_DT_ENDPOINT_SIZE,
132 .bDescriptorType = USB_DT_ENDPOINT,
133 .bEndpointAddress = 1 | USB_DIR_IN,
134 .bmAttributes = USB_ENDPOINT_XFER_BULK,
135 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
136};
137
138const struct usb_endpoint_descriptor_no_audio fs_source = {
139 .bLength = USB_DT_ENDPOINT_SIZE,
140 .bDescriptorType = USB_DT_ENDPOINT,
141 .bEndpointAddress = 2 | USB_DIR_OUT,
142 .bmAttributes = USB_ENDPOINT_XFER_BULK,
143 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
144};
145
146const struct usb_endpoint_descriptor_no_audio fs_intr = {
147 .bLength = USB_DT_ENDPOINT_SIZE,
148 .bDescriptorType = USB_DT_ENDPOINT,
149 .bEndpointAddress = 3 | USB_DIR_IN,
150 .bmAttributes = USB_ENDPOINT_XFER_INT,
151 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
152 .bInterval = 6,
153};
154
155const struct usb_endpoint_descriptor_no_audio hs_sink = {
156 .bLength = USB_DT_ENDPOINT_SIZE,
157 .bDescriptorType = USB_DT_ENDPOINT,
158 .bEndpointAddress = 1 | USB_DIR_IN,
159 .bmAttributes = USB_ENDPOINT_XFER_BULK,
160 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
161};
162
163const struct usb_endpoint_descriptor_no_audio hs_source = {
164 .bLength = USB_DT_ENDPOINT_SIZE,
165 .bDescriptorType = USB_DT_ENDPOINT,
166 .bEndpointAddress = 2 | USB_DIR_OUT,
167 .bmAttributes = USB_ENDPOINT_XFER_BULK,
168 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
169};
170
171const struct usb_endpoint_descriptor_no_audio hs_intr = {
172 .bLength = USB_DT_ENDPOINT_SIZE,
173 .bDescriptorType = USB_DT_ENDPOINT,
174 .bEndpointAddress = 3 | USB_DIR_IN,
175 .bmAttributes = USB_ENDPOINT_XFER_INT,
176 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
177 .bInterval = 6,
178};
179
180const struct usb_endpoint_descriptor_no_audio ss_sink = {
181 .bLength = USB_DT_ENDPOINT_SIZE,
182 .bDescriptorType = USB_DT_ENDPOINT,
183 .bEndpointAddress = 1 | USB_DIR_IN,
184 .bmAttributes = USB_ENDPOINT_XFER_BULK,
185 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
186};
187
188const struct usb_endpoint_descriptor_no_audio ss_source = {
189 .bLength = USB_DT_ENDPOINT_SIZE,
190 .bDescriptorType = USB_DT_ENDPOINT,
191 .bEndpointAddress = 2 | USB_DIR_OUT,
192 .bmAttributes = USB_ENDPOINT_XFER_BULK,
193 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
194};
195
196const struct usb_endpoint_descriptor_no_audio ss_intr = {
197 .bLength = USB_DT_ENDPOINT_SIZE,
198 .bDescriptorType = USB_DT_ENDPOINT,
199 .bEndpointAddress = 3 | USB_DIR_IN,
200 .bmAttributes = USB_ENDPOINT_XFER_INT,
201 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
202 .bInterval = 6,
203};
204
205const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
206 .bLength = sizeof(ss_sink_comp),
207 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800208 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700209};
210
211const struct usb_ss_ep_comp_descriptor ss_source_comp = {
212 .bLength = sizeof(ss_source_comp),
213 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
Jerry Zhang2a141682017-02-13 14:24:13 -0800214 .bMaxBurst = 6,
Jerry Zhang487be612016-10-24 12:10:41 -0700215};
216
217const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
218 .bLength = sizeof(ss_intr_comp),
219 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
220};
221
222const struct func_desc mtp_fs_descriptors = {
223 .intf = mtp_interface_desc,
224 .sink = fs_sink,
225 .source = fs_source,
226 .intr = fs_intr,
227};
228
229const struct func_desc mtp_hs_descriptors = {
230 .intf = mtp_interface_desc,
231 .sink = hs_sink,
232 .source = hs_source,
233 .intr = hs_intr,
234};
235
236const struct ss_func_desc mtp_ss_descriptors = {
237 .intf = mtp_interface_desc,
238 .sink = ss_sink,
239 .sink_comp = ss_sink_comp,
240 .source = ss_source,
241 .source_comp = ss_source_comp,
242 .intr = ss_intr,
243 .intr_comp = ss_intr_comp,
244};
245
246const struct func_desc ptp_fs_descriptors = {
247 .intf = ptp_interface_desc,
248 .sink = fs_sink,
249 .source = fs_source,
250 .intr = fs_intr,
251};
252
253const struct func_desc ptp_hs_descriptors = {
254 .intf = ptp_interface_desc,
255 .sink = hs_sink,
256 .source = hs_source,
257 .intr = hs_intr,
258};
259
260const struct ss_func_desc ptp_ss_descriptors = {
261 .intf = ptp_interface_desc,
262 .sink = ss_sink,
263 .sink_comp = ss_sink_comp,
264 .source = ss_source,
265 .source_comp = ss_source_comp,
266 .intr = ss_intr,
267 .intr_comp = ss_intr_comp,
268};
269
Jerry Zhang6a790522017-01-11 15:17:53 -0800270#define STR_INTERFACE "MTP"
Jerry Zhang487be612016-10-24 12:10:41 -0700271const struct {
272 struct usb_functionfs_strings_head header;
Jerry Zhang6a790522017-01-11 15:17:53 -0800273 struct {
274 __le16 code;
275 const char str1[sizeof(STR_INTERFACE)];
276 } __attribute__((packed)) lang0;
Jerry Zhang487be612016-10-24 12:10:41 -0700277} __attribute__((packed)) strings = {
278 .header = {
279 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
280 .length = cpu_to_le32(sizeof(strings)),
Jerry Zhang6a790522017-01-11 15:17:53 -0800281 .str_count = cpu_to_le32(1),
282 .lang_count = cpu_to_le32(1),
283 },
284 .lang0 = {
285 .code = cpu_to_le16(0x0409),
286 .str1 = STR_INTERFACE,
Jerry Zhang487be612016-10-24 12:10:41 -0700287 },
288};
289
290} // anonymous namespace
291
292namespace android {
293
294MtpFfsHandle::MtpFfsHandle() :
295 mMaxWrite(USB_FFS_MAX_WRITE),
296 mMaxRead(USB_FFS_MAX_READ) {}
297
298MtpFfsHandle::~MtpFfsHandle() {}
299
300void MtpFfsHandle::closeEndpoints() {
301 mIntr.reset();
302 mBulkIn.reset();
303 mBulkOut.reset();
304}
305
306bool MtpFfsHandle::initFunctionfs() {
307 ssize_t ret;
308 struct desc_v1 v1_descriptor;
309 struct desc_v2 v2_descriptor;
310
311 v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
312 v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
313 v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
314 FUNCTIONFS_HAS_SS_DESC;
315 v2_descriptor.fs_count = 4;
316 v2_descriptor.hs_count = 4;
317 v2_descriptor.ss_count = 7;
318 v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
319 v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
320 v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
321
322 if (mControl < 0) { // might have already done this before
323 mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
324 if (mControl < 0) {
325 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
326 goto err;
327 }
328
329 ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
330 if (ret < 0) {
331 v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
332 v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
333 v1_descriptor.header.fs_count = 4;
334 v1_descriptor.header.hs_count = 4;
335 v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
336 v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
337 PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
338 ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
339 if (ret < 0) {
340 PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
341 goto err;
342 }
343 }
344 ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
345 if (ret < 0) {
346 PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
347 goto err;
348 }
349 }
350 if (mBulkIn > -1 || mBulkOut > -1 || mIntr > -1)
351 LOG(WARNING) << "Endpoints were not closed before configure!";
352
Jerry Zhang487be612016-10-24 12:10:41 -0700353 return true;
354
355err:
Jerry Zhang487be612016-10-24 12:10:41 -0700356 closeConfig();
357 return false;
358}
359
360void MtpFfsHandle::closeConfig() {
361 mControl.reset();
362}
363
364int MtpFfsHandle::writeHandle(int fd, const void* data, int len) {
365 LOG(VERBOSE) << "MTP about to write fd = " << fd << ", len=" << len;
366 int ret = 0;
367 const char* buf = static_cast<const char*>(data);
368 while (len > 0) {
369 int write_len = std::min(mMaxWrite, len);
370 int n = TEMP_FAILURE_RETRY(::write(fd, buf, write_len));
371
372 if (n < 0) {
373 PLOG(ERROR) << "write ERROR: fd = " << fd << ", n = " << n;
374 return -1;
375 } else if (n < write_len) {
376 errno = EIO;
377 PLOG(ERROR) << "less written than expected";
378 return -1;
379 }
380 buf += n;
381 len -= n;
382 ret += n;
383 }
384 return ret;
385}
386
387int MtpFfsHandle::readHandle(int fd, void* data, int len) {
388 LOG(VERBOSE) << "MTP about to read fd = " << fd << ", len=" << len;
389 int ret = 0;
390 char* buf = static_cast<char*>(data);
391 while (len > 0) {
392 int read_len = std::min(mMaxRead, len);
393 int n = TEMP_FAILURE_RETRY(::read(fd, buf, read_len));
394 if (n < 0) {
395 PLOG(ERROR) << "read ERROR: fd = " << fd << ", n = " << n;
396 return -1;
397 }
398 ret += n;
399 if (n < read_len) // done reading early
400 break;
401 buf += n;
402 len -= n;
403 }
404 return ret;
405}
406
407int MtpFfsHandle::spliceReadHandle(int fd, int pipe_out, int len) {
408 LOG(VERBOSE) << "MTP about to splice read fd = " << fd << ", len=" << len;
409 int ret = 0;
410 loff_t dummyoff;
411 while (len > 0) {
412 int read_len = std::min(mMaxRead, len);
413 dummyoff = 0;
414 int n = TEMP_FAILURE_RETRY(splice(fd, &dummyoff, pipe_out, nullptr, read_len, 0));
415 if (n < 0) {
416 PLOG(ERROR) << "splice read ERROR: fd = " << fd << ", n = " << n;
417 return -1;
418 }
419 ret += n;
420 if (n < read_len) // done reading early
421 break;
422 len -= n;
423 }
424 return ret;
425}
426
427int MtpFfsHandle::read(void* data, int len) {
428 return readHandle(mBulkOut, data, len);
429}
430
431int MtpFfsHandle::write(const void* data, int len) {
432 return writeHandle(mBulkIn, data, len);
433}
434
435int MtpFfsHandle::start() {
436 mLock.lock();
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800437
438 mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
439 if (mBulkIn < 0) {
440 PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
441 return -1;
442 }
443
444 mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
445 if (mBulkOut < 0) {
446 PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
447 return -1;
448 }
449
450 mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
451 if (mIntr < 0) {
452 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
453 return -1;
454 }
455
456 mBuffer1.resize(MAX_FILE_CHUNK_SIZE);
457 mBuffer2.resize(MAX_FILE_CHUNK_SIZE);
458 posix_madvise(mBuffer1.data(), MAX_FILE_CHUNK_SIZE,
459 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
460 posix_madvise(mBuffer2.data(), MAX_FILE_CHUNK_SIZE,
461 POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
462
463 // Get device specific r/w size
464 mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
465 mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);
466
Jerry Zhangb4f54262017-02-02 18:14:33 -0800467 size_t attempts = 0;
468 while (mMaxWrite >= USB_FFS_MAX_WRITE && mMaxRead >= USB_FFS_MAX_READ &&
469 attempts < ENDPOINT_ALLOC_RETRIES) {
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800470 // If larger contiguous chunks of memory aren't available, attempt to try
471 // smaller allocations.
472 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) ||
473 ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) {
Jerry Zhangb4f54262017-02-02 18:14:33 -0800474 if (errno == ENODEV) {
475 // Driver hasn't enabled endpoints yet.
476 std::this_thread::sleep_for(std::chrono::milliseconds(100));
477 attempts += 1;
478 continue;
479 }
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800480 mMaxWrite /= 2;
481 mMaxRead /=2;
482 } else {
483 return 0;
484 }
485 }
Jerry Zhangb4f54262017-02-02 18:14:33 -0800486 // Try to start MtpServer anyway, with the smallest max r/w values
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800487 PLOG(ERROR) << "Functionfs could not allocate any memory!";
Jerry Zhangb4f54262017-02-02 18:14:33 -0800488 return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700489}
490
491int MtpFfsHandle::configure(bool usePtp) {
492 // Wait till previous server invocation has closed
Jerry Zhang0475d912017-04-03 11:24:48 -0700493 if (!mLock.try_lock_for(std::chrono::milliseconds(1000))) {
494 LOG(ERROR) << "MtpServer was unable to get configure lock";
495 return -1;
496 }
497 int ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700498
499 // If ptp is changed, the configuration must be rewritten
500 if (mPtp != usePtp) {
501 closeEndpoints();
502 closeConfig();
503 }
504 mPtp = usePtp;
505
506 if (!initFunctionfs()) {
Jerry Zhang0475d912017-04-03 11:24:48 -0700507 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700508 }
Jerry Zhang0475d912017-04-03 11:24:48 -0700509 mLock.unlock();
510 return ret;
Jerry Zhang487be612016-10-24 12:10:41 -0700511}
512
513void MtpFfsHandle::close() {
514 closeEndpoints();
515 mLock.unlock();
516}
517
518/* Read from USB and write to a local file. */
519int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
520 // When receiving files, the incoming length is given in 32 bits.
521 // A >4G file is given as 0xFFFFFFFF
522 uint32_t file_length = mfr.length;
523 uint64_t offset = lseek(mfr.fd, 0, SEEK_CUR);
524
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800525 char *data = mBuffer1.data();
526 char *data2 = mBuffer2.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700527
528 struct aiocb aio;
529 aio.aio_fildes = mfr.fd;
530 aio.aio_buf = nullptr;
531 struct aiocb *aiol[] = {&aio};
532 int ret;
533 size_t length;
534 bool read = false;
535 bool write = false;
536
537 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
538
539 // Break down the file into pieces that fit in buffers
540 while (file_length > 0 || write) {
541 if (file_length > 0) {
542 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
543
Jerry Zhang7063c932017-04-04 15:06:10 -0700544 // Read data from USB, handle errors after waiting for write thread.
545 ret = readHandle(mBulkOut, data, length);
Jerry Zhang487be612016-10-24 12:10:41 -0700546
547 if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700548 ret = -1;
Jerry Zhang487be612016-10-24 12:10:41 -0700549 errno = EIO;
Jerry Zhang487be612016-10-24 12:10:41 -0700550 }
551 read = true;
552 }
553
554 if (write) {
555 // get the return status of the last write request
556 aio_suspend(aiol, 1, nullptr);
557
558 int written = aio_return(&aio);
559 if (written == -1) {
560 errno = aio_error(&aio);
561 return -1;
562 }
563 if (static_cast<size_t>(written) < aio.aio_nbytes) {
564 errno = EIO;
565 return -1;
566 }
567 write = false;
568 }
569
Jerry Zhang7063c932017-04-04 15:06:10 -0700570 // If there was an error reading above
571 if (ret == -1) {
572 return -1;
573 }
574
Jerry Zhang487be612016-10-24 12:10:41 -0700575 if (read) {
576 // Enqueue a new write request
577 aio.aio_buf = data;
578 aio.aio_sink = mfr.fd;
579 aio.aio_offset = offset;
580 aio.aio_nbytes = ret;
581 aio_write(&aio);
582
583 if (file_length == MAX_MTP_FILE_SIZE) {
584 // For larger files, receive until a short packet is received.
585 if (static_cast<size_t>(ret) < length) {
586 file_length = 0;
587 }
588 } else {
589 file_length -= ret;
590 }
591
592 offset += ret;
593 std::swap(data, data2);
594
595 write = true;
596 read = false;
597 }
598 }
599 return 0;
600}
601
602/* Read from a local file and send over USB. */
603int MtpFfsHandle::sendFile(mtp_file_range mfr) {
604 uint64_t file_length = mfr.length;
605 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
606 file_length + sizeof(mtp_data_header));
Jerry Zhang44180302017-02-03 16:31:31 -0800607 uint64_t offset = mfr.offset;
Jerry Zhang487be612016-10-24 12:10:41 -0700608 struct usb_endpoint_descriptor mBulkIn_desc;
609 int packet_size;
610
611 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkIn_desc))) {
612 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
613 packet_size = MAX_PACKET_SIZE_HS;
614 } else {
615 packet_size = mBulkIn_desc.wMaxPacketSize;
616 }
617
Jerry Zhang44180302017-02-03 16:31:31 -0800618 // If file_length is larger than a size_t, truncating would produce the wrong comparison.
619 // Instead, promote the left side to 64 bits, then truncate the small result.
620 int init_read_len = std::min(
621 static_cast<uint64_t>(packet_size - sizeof(mtp_data_header)), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700622
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800623 char *data = mBuffer1.data();
624 char *data2 = mBuffer2.data();
Jerry Zhang487be612016-10-24 12:10:41 -0700625
Jerry Zhange9d94422017-01-18 12:03:56 -0800626 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
Jerry Zhange9d94422017-01-18 12:03:56 -0800627
Jerry Zhang487be612016-10-24 12:10:41 -0700628 struct aiocb aio;
629 aio.aio_fildes = mfr.fd;
630 struct aiocb *aiol[] = {&aio};
631 int ret, length;
Jerry Zhang7063c932017-04-04 15:06:10 -0700632 int error = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700633 bool read = false;
634 bool write = false;
635
636 // Send the header data
637 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(data);
638 header->length = __cpu_to_le32(given_length);
639 header->type = __cpu_to_le16(2); /* data packet */
640 header->command = __cpu_to_le16(mfr.command);
641 header->transaction_id = __cpu_to_le32(mfr.transaction_id);
642
643 // Some hosts don't support header/data separation even though MTP allows it
644 // Handle by filling first packet with initial file data
645 if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
646 sizeof(mtp_data_header), init_read_len, offset))
647 != init_read_len) return -1;
Jerry Zhang44180302017-02-03 16:31:31 -0800648 if (writeHandle(mBulkIn, data, sizeof(mtp_data_header) + init_read_len) == -1) return -1;
649 if (file_length == static_cast<unsigned>(init_read_len)) return 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700650 file_length -= init_read_len;
651 offset += init_read_len;
Yunlian Jiang746f8ac2017-02-21 16:10:45 -0800652 ret = 0;
Jerry Zhang487be612016-10-24 12:10:41 -0700653
Jerry Zhang487be612016-10-24 12:10:41 -0700654 // Break down the file into pieces that fit in buffers
655 while(file_length > 0) {
656 if (read) {
657 // Wait for the previous read to finish
658 aio_suspend(aiol, 1, nullptr);
659 ret = aio_return(&aio);
660 if (ret == -1) {
661 errno = aio_error(&aio);
662 return -1;
663 }
664 if (static_cast<size_t>(ret) < aio.aio_nbytes) {
665 errno = EIO;
666 return -1;
667 }
668
669 file_length -= ret;
670 offset += ret;
671 std::swap(data, data2);
672 read = false;
673 write = true;
674 }
675
Jerry Zhang7063c932017-04-04 15:06:10 -0700676 if (error == -1) {
677 return -1;
678 }
679
Jerry Zhang487be612016-10-24 12:10:41 -0700680 if (file_length > 0) {
Jerry Zhangcc9d0fd2017-01-27 10:29:59 -0800681 length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
Jerry Zhang487be612016-10-24 12:10:41 -0700682 // Queue up another read
683 aio.aio_buf = data;
684 aio.aio_offset = offset;
685 aio.aio_nbytes = length;
686 aio_read(&aio);
687 read = true;
688 }
689
690 if (write) {
Jerry Zhang7063c932017-04-04 15:06:10 -0700691 if (writeHandle(mBulkIn, data2, ret) == -1) {
692 error = -1;
693 }
Jerry Zhang487be612016-10-24 12:10:41 -0700694 write = false;
695 }
696 }
697
698 if (given_length == MAX_MTP_FILE_SIZE && ret % packet_size == 0) {
699 // If the last packet wasn't short, send a final empty packet
700 if (writeHandle(mBulkIn, data, 0) == -1) return -1;
701 }
702
703 return 0;
704}
705
706int MtpFfsHandle::sendEvent(mtp_event me) {
707 unsigned length = me.length;
708 int ret = writeHandle(mIntr, me.data, length);
709 return static_cast<unsigned>(ret) == length ? 0 : -1;
710}
711
712} // namespace android
713
714IMtpHandle *get_ffs_handle() {
715 return new android::MtpFfsHandle();
716}
717