blob: 9f0f8bfd19b57b49b335789c129746e09c1ebae6 [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"
38
39#define cpu_to_le16(x) htole16(x)
40#define cpu_to_le32(x) htole32(x)
41
Jerry Zhang5a804b92016-12-15 17:07:38 -080042#define FUNCTIONFS_ENDPOINT_ALLOC _IOR('g', 131, __u32)
43
Jerry Zhang487be612016-10-24 12:10:41 -070044namespace {
45
46constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
47constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
48constexpr char FFS_MTP_EP_INTR[] = "/dev/usb-ffs/mtp/ep3";
49
50constexpr int MAX_PACKET_SIZE_FS = 64;
51constexpr int MAX_PACKET_SIZE_HS = 512;
52constexpr int MAX_PACKET_SIZE_SS = 1024;
53
54// Must be divisible by all max packet size values
55constexpr int MAX_FILE_CHUNK_SIZE = 3145728;
56
57// Safe values since some devices cannot handle large DMAs
58// To get good performance, override these with
59// higher values per device using the properties
60// sys.usb.ffs.max_read and sys.usb.ffs.max_write
61constexpr int USB_FFS_MAX_WRITE = 32768;
62constexpr int USB_FFS_MAX_READ = 32768;
63
64constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
65
66struct func_desc {
67 struct usb_interface_descriptor intf;
68 struct usb_endpoint_descriptor_no_audio sink;
69 struct usb_endpoint_descriptor_no_audio source;
70 struct usb_endpoint_descriptor_no_audio intr;
71} __attribute__((packed));
72
73struct ss_func_desc {
74 struct usb_interface_descriptor intf;
75 struct usb_endpoint_descriptor_no_audio sink;
76 struct usb_ss_ep_comp_descriptor sink_comp;
77 struct usb_endpoint_descriptor_no_audio source;
78 struct usb_ss_ep_comp_descriptor source_comp;
79 struct usb_endpoint_descriptor_no_audio intr;
80 struct usb_ss_ep_comp_descriptor intr_comp;
81} __attribute__((packed));
82
83struct desc_v1 {
84 struct usb_functionfs_descs_head_v1 {
85 __le32 magic;
86 __le32 length;
87 __le32 fs_count;
88 __le32 hs_count;
89 } __attribute__((packed)) header;
90 struct func_desc fs_descs, hs_descs;
91} __attribute__((packed));
92
93struct desc_v2 {
94 struct usb_functionfs_descs_head_v2 header;
95 // The rest of the structure depends on the flags in the header.
96 __le32 fs_count;
97 __le32 hs_count;
98 __le32 ss_count;
99 struct func_desc fs_descs, hs_descs;
100 struct ss_func_desc ss_descs;
101} __attribute__((packed));
102
103const struct usb_interface_descriptor mtp_interface_desc = {
104 .bLength = USB_DT_INTERFACE_SIZE,
105 .bDescriptorType = USB_DT_INTERFACE,
106 .bInterfaceNumber = 0,
107 .bNumEndpoints = 3,
108 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
109 .bInterfaceSubClass = 1,
110 .bInterfaceProtocol = 1,
Jerry Zhang6a790522017-01-11 15:17:53 -0800111 .iInterface = 1,
Jerry Zhang487be612016-10-24 12:10:41 -0700112};
113
114const struct usb_interface_descriptor ptp_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,
122};
123
124const struct usb_endpoint_descriptor_no_audio fs_sink = {
125 .bLength = USB_DT_ENDPOINT_SIZE,
126 .bDescriptorType = USB_DT_ENDPOINT,
127 .bEndpointAddress = 1 | USB_DIR_IN,
128 .bmAttributes = USB_ENDPOINT_XFER_BULK,
129 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
130};
131
132const struct usb_endpoint_descriptor_no_audio fs_source = {
133 .bLength = USB_DT_ENDPOINT_SIZE,
134 .bDescriptorType = USB_DT_ENDPOINT,
135 .bEndpointAddress = 2 | USB_DIR_OUT,
136 .bmAttributes = USB_ENDPOINT_XFER_BULK,
137 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
138};
139
140const struct usb_endpoint_descriptor_no_audio fs_intr = {
141 .bLength = USB_DT_ENDPOINT_SIZE,
142 .bDescriptorType = USB_DT_ENDPOINT,
143 .bEndpointAddress = 3 | USB_DIR_IN,
144 .bmAttributes = USB_ENDPOINT_XFER_INT,
145 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
146 .bInterval = 6,
147};
148
149const struct usb_endpoint_descriptor_no_audio hs_sink = {
150 .bLength = USB_DT_ENDPOINT_SIZE,
151 .bDescriptorType = USB_DT_ENDPOINT,
152 .bEndpointAddress = 1 | USB_DIR_IN,
153 .bmAttributes = USB_ENDPOINT_XFER_BULK,
154 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
155};
156
157const struct usb_endpoint_descriptor_no_audio hs_source = {
158 .bLength = USB_DT_ENDPOINT_SIZE,
159 .bDescriptorType = USB_DT_ENDPOINT,
160 .bEndpointAddress = 2 | USB_DIR_OUT,
161 .bmAttributes = USB_ENDPOINT_XFER_BULK,
162 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
163};
164
165const struct usb_endpoint_descriptor_no_audio hs_intr = {
166 .bLength = USB_DT_ENDPOINT_SIZE,
167 .bDescriptorType = USB_DT_ENDPOINT,
168 .bEndpointAddress = 3 | USB_DIR_IN,
169 .bmAttributes = USB_ENDPOINT_XFER_INT,
170 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
171 .bInterval = 6,
172};
173
174const struct usb_endpoint_descriptor_no_audio ss_sink = {
175 .bLength = USB_DT_ENDPOINT_SIZE,
176 .bDescriptorType = USB_DT_ENDPOINT,
177 .bEndpointAddress = 1 | USB_DIR_IN,
178 .bmAttributes = USB_ENDPOINT_XFER_BULK,
179 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
180};
181
182const struct usb_endpoint_descriptor_no_audio ss_source = {
183 .bLength = USB_DT_ENDPOINT_SIZE,
184 .bDescriptorType = USB_DT_ENDPOINT,
185 .bEndpointAddress = 2 | USB_DIR_OUT,
186 .bmAttributes = USB_ENDPOINT_XFER_BULK,
187 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
188};
189
190const struct usb_endpoint_descriptor_no_audio ss_intr = {
191 .bLength = USB_DT_ENDPOINT_SIZE,
192 .bDescriptorType = USB_DT_ENDPOINT,
193 .bEndpointAddress = 3 | USB_DIR_IN,
194 .bmAttributes = USB_ENDPOINT_XFER_INT,
195 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
196 .bInterval = 6,
197};
198
199const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
200 .bLength = sizeof(ss_sink_comp),
201 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
202 .bMaxBurst = 2,
203};
204
205const struct usb_ss_ep_comp_descriptor ss_source_comp = {
206 .bLength = sizeof(ss_source_comp),
207 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
208 .bMaxBurst = 2,
209};
210
211const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
212 .bLength = sizeof(ss_intr_comp),
213 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
214};
215
216const struct func_desc mtp_fs_descriptors = {
217 .intf = mtp_interface_desc,
218 .sink = fs_sink,
219 .source = fs_source,
220 .intr = fs_intr,
221};
222
223const struct func_desc mtp_hs_descriptors = {
224 .intf = mtp_interface_desc,
225 .sink = hs_sink,
226 .source = hs_source,
227 .intr = hs_intr,
228};
229
230const struct ss_func_desc mtp_ss_descriptors = {
231 .intf = mtp_interface_desc,
232 .sink = ss_sink,
233 .sink_comp = ss_sink_comp,
234 .source = ss_source,
235 .source_comp = ss_source_comp,
236 .intr = ss_intr,
237 .intr_comp = ss_intr_comp,
238};
239
240const struct func_desc ptp_fs_descriptors = {
241 .intf = ptp_interface_desc,
242 .sink = fs_sink,
243 .source = fs_source,
244 .intr = fs_intr,
245};
246
247const struct func_desc ptp_hs_descriptors = {
248 .intf = ptp_interface_desc,
249 .sink = hs_sink,
250 .source = hs_source,
251 .intr = hs_intr,
252};
253
254const struct ss_func_desc ptp_ss_descriptors = {
255 .intf = ptp_interface_desc,
256 .sink = ss_sink,
257 .sink_comp = ss_sink_comp,
258 .source = ss_source,
259 .source_comp = ss_source_comp,
260 .intr = ss_intr,
261 .intr_comp = ss_intr_comp,
262};
263
Jerry Zhang6a790522017-01-11 15:17:53 -0800264#define STR_INTERFACE "MTP"
Jerry Zhang487be612016-10-24 12:10:41 -0700265const struct {
266 struct usb_functionfs_strings_head header;
Jerry Zhang6a790522017-01-11 15:17:53 -0800267 struct {
268 __le16 code;
269 const char str1[sizeof(STR_INTERFACE)];
270 } __attribute__((packed)) lang0;
Jerry Zhang487be612016-10-24 12:10:41 -0700271} __attribute__((packed)) strings = {
272 .header = {
273 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
274 .length = cpu_to_le32(sizeof(strings)),
Jerry Zhang6a790522017-01-11 15:17:53 -0800275 .str_count = cpu_to_le32(1),
276 .lang_count = cpu_to_le32(1),
277 },
278 .lang0 = {
279 .code = cpu_to_le16(0x0409),
280 .str1 = STR_INTERFACE,
Jerry Zhang487be612016-10-24 12:10:41 -0700281 },
282};
283
284} // anonymous namespace
285
286namespace android {
287
288MtpFfsHandle::MtpFfsHandle() :
289 mMaxWrite(USB_FFS_MAX_WRITE),
290 mMaxRead(USB_FFS_MAX_READ) {}
291
292MtpFfsHandle::~MtpFfsHandle() {}
293
294void MtpFfsHandle::closeEndpoints() {
295 mIntr.reset();
296 mBulkIn.reset();
297 mBulkOut.reset();
298}
299
300bool MtpFfsHandle::initFunctionfs() {
301 ssize_t ret;
302 struct desc_v1 v1_descriptor;
303 struct desc_v2 v2_descriptor;
304
305 v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
306 v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
307 v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
308 FUNCTIONFS_HAS_SS_DESC;
309 v2_descriptor.fs_count = 4;
310 v2_descriptor.hs_count = 4;
311 v2_descriptor.ss_count = 7;
312 v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
313 v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
314 v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
315
316 if (mControl < 0) { // might have already done this before
317 mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
318 if (mControl < 0) {
319 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
320 goto err;
321 }
322
323 ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
324 if (ret < 0) {
325 v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
326 v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
327 v1_descriptor.header.fs_count = 4;
328 v1_descriptor.header.hs_count = 4;
329 v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
330 v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
331 PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
332 ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
333 if (ret < 0) {
334 PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
335 goto err;
336 }
337 }
338 ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
339 if (ret < 0) {
340 PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
341 goto err;
342 }
343 }
344 if (mBulkIn > -1 || mBulkOut > -1 || mIntr > -1)
345 LOG(WARNING) << "Endpoints were not closed before configure!";
346
347 mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
348 if (mBulkIn < 0) {
349 PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
350 goto err;
351 }
352
353 mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
354 if (mBulkOut < 0) {
355 PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
356 goto err;
357 }
358
359 mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
360 if (mIntr < 0) {
361 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
362 goto err;
363 }
364
365 return true;
366
367err:
368 closeEndpoints();
369 closeConfig();
370 return false;
371}
372
373void MtpFfsHandle::closeConfig() {
374 mControl.reset();
375}
376
377int MtpFfsHandle::writeHandle(int fd, const void* data, int len) {
378 LOG(VERBOSE) << "MTP about to write fd = " << fd << ", len=" << len;
379 int ret = 0;
380 const char* buf = static_cast<const char*>(data);
381 while (len > 0) {
382 int write_len = std::min(mMaxWrite, len);
383 int n = TEMP_FAILURE_RETRY(::write(fd, buf, write_len));
384
385 if (n < 0) {
386 PLOG(ERROR) << "write ERROR: fd = " << fd << ", n = " << n;
387 return -1;
388 } else if (n < write_len) {
389 errno = EIO;
390 PLOG(ERROR) << "less written than expected";
391 return -1;
392 }
393 buf += n;
394 len -= n;
395 ret += n;
396 }
397 return ret;
398}
399
400int MtpFfsHandle::readHandle(int fd, void* data, int len) {
401 LOG(VERBOSE) << "MTP about to read fd = " << fd << ", len=" << len;
402 int ret = 0;
403 char* buf = static_cast<char*>(data);
404 while (len > 0) {
405 int read_len = std::min(mMaxRead, len);
406 int n = TEMP_FAILURE_RETRY(::read(fd, buf, read_len));
407 if (n < 0) {
408 PLOG(ERROR) << "read ERROR: fd = " << fd << ", n = " << n;
409 return -1;
410 }
411 ret += n;
412 if (n < read_len) // done reading early
413 break;
414 buf += n;
415 len -= n;
416 }
417 return ret;
418}
419
420int MtpFfsHandle::spliceReadHandle(int fd, int pipe_out, int len) {
421 LOG(VERBOSE) << "MTP about to splice read fd = " << fd << ", len=" << len;
422 int ret = 0;
423 loff_t dummyoff;
424 while (len > 0) {
425 int read_len = std::min(mMaxRead, len);
426 dummyoff = 0;
427 int n = TEMP_FAILURE_RETRY(splice(fd, &dummyoff, pipe_out, nullptr, read_len, 0));
428 if (n < 0) {
429 PLOG(ERROR) << "splice read ERROR: fd = " << fd << ", n = " << n;
430 return -1;
431 }
432 ret += n;
433 if (n < read_len) // done reading early
434 break;
435 len -= n;
436 }
437 return ret;
438}
439
440int MtpFfsHandle::read(void* data, int len) {
441 return readHandle(mBulkOut, data, len);
442}
443
444int MtpFfsHandle::write(const void* data, int len) {
445 return writeHandle(mBulkIn, data, len);
446}
447
448int MtpFfsHandle::start() {
449 mLock.lock();
450 return 0;
451}
452
453int MtpFfsHandle::configure(bool usePtp) {
454 // Wait till previous server invocation has closed
455 std::lock_guard<std::mutex> lk(mLock);
456
457 // If ptp is changed, the configuration must be rewritten
458 if (mPtp != usePtp) {
459 closeEndpoints();
460 closeConfig();
461 }
462 mPtp = usePtp;
463
464 if (!initFunctionfs()) {
465 return -1;
466 }
467
468 // Get device specific r/w size
469 mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", 0);
470 mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", 0);
471 if (!mMaxWrite)
472 mMaxWrite = USB_FFS_MAX_WRITE;
473 if (!mMaxRead)
474 mMaxRead = USB_FFS_MAX_READ;
475 return 0;
476}
477
478void MtpFfsHandle::close() {
479 closeEndpoints();
480 mLock.unlock();
481}
482
Jerry Zhang5a804b92016-12-15 17:07:38 -0800483class ScopedEndpointBufferAlloc {
484private:
485 const int mFd;
486 const unsigned int mAllocSize;
487public:
488 ScopedEndpointBufferAlloc(int fd, unsigned alloc_size) :
489 mFd(fd),
490 mAllocSize(alloc_size) {
491 if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mAllocSize)))
Jerry Zhange9d94422017-01-18 12:03:56 -0800492 PLOG(ERROR) << "FFS endpoint alloc failed!";
Jerry Zhang5a804b92016-12-15 17:07:38 -0800493 }
494
495 ~ScopedEndpointBufferAlloc() {
496 if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(0)))
Jerry Zhange9d94422017-01-18 12:03:56 -0800497 PLOG(ERROR) << "FFS endpoint alloc reset failed!";
Jerry Zhang5a804b92016-12-15 17:07:38 -0800498 }
Jerry Zhange9d94422017-01-18 12:03:56 -0800499
500 DISALLOW_COPY_AND_ASSIGN(ScopedEndpointBufferAlloc);
Jerry Zhang5a804b92016-12-15 17:07:38 -0800501};
502
Jerry Zhang487be612016-10-24 12:10:41 -0700503/* Read from USB and write to a local file. */
504int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
505 // When receiving files, the incoming length is given in 32 bits.
506 // A >4G file is given as 0xFFFFFFFF
507 uint32_t file_length = mfr.length;
508 uint64_t offset = lseek(mfr.fd, 0, SEEK_CUR);
509
510 int buf1_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
511 std::vector<char> buf1(buf1_len);
512 char* data = buf1.data();
513
514 // If necessary, allocate a second buffer for background r/w
515 int buf2_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE),
516 file_length - MAX_FILE_CHUNK_SIZE);
517 std::vector<char> buf2(std::max(0, buf2_len));
518 char *data2 = buf2.data();
519
520 struct aiocb aio;
521 aio.aio_fildes = mfr.fd;
522 aio.aio_buf = nullptr;
523 struct aiocb *aiol[] = {&aio};
524 int ret;
525 size_t length;
526 bool read = false;
527 bool write = false;
528
529 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
Jerry Zhange9d94422017-01-18 12:03:56 -0800530 posix_madvise(data, buf1_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
531 posix_madvise(data2, buf2_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
532 ScopedEndpointBufferAlloc scoped_alloc(mBulkOut, mMaxRead);
Jerry Zhang487be612016-10-24 12:10:41 -0700533
534 // Break down the file into pieces that fit in buffers
535 while (file_length > 0 || write) {
536 if (file_length > 0) {
537 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
538
539 // Read data from USB
540 if ((ret = readHandle(mBulkOut, data, length)) == -1) {
541 return -1;
542 }
543
544 if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
545 errno = EIO;
546 return -1;
547 }
548 read = true;
549 }
550
551 if (write) {
552 // get the return status of the last write request
553 aio_suspend(aiol, 1, nullptr);
554
555 int written = aio_return(&aio);
556 if (written == -1) {
557 errno = aio_error(&aio);
558 return -1;
559 }
560 if (static_cast<size_t>(written) < aio.aio_nbytes) {
561 errno = EIO;
562 return -1;
563 }
564 write = false;
565 }
566
567 if (read) {
568 // Enqueue a new write request
569 aio.aio_buf = data;
570 aio.aio_sink = mfr.fd;
571 aio.aio_offset = offset;
572 aio.aio_nbytes = ret;
573 aio_write(&aio);
574
575 if (file_length == MAX_MTP_FILE_SIZE) {
576 // For larger files, receive until a short packet is received.
577 if (static_cast<size_t>(ret) < length) {
578 file_length = 0;
579 }
580 } else {
581 file_length -= ret;
582 }
583
584 offset += ret;
585 std::swap(data, data2);
586
587 write = true;
588 read = false;
589 }
590 }
591 return 0;
592}
593
594/* Read from a local file and send over USB. */
595int MtpFfsHandle::sendFile(mtp_file_range mfr) {
596 uint64_t file_length = mfr.length;
597 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
598 file_length + sizeof(mtp_data_header));
599 uint64_t offset = 0;
600 struct usb_endpoint_descriptor mBulkIn_desc;
601 int packet_size;
602
603 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkIn_desc))) {
604 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
605 packet_size = MAX_PACKET_SIZE_HS;
606 } else {
607 packet_size = mBulkIn_desc.wMaxPacketSize;
608 }
609
Jerry Zhang487be612016-10-24 12:10:41 -0700610 int init_read_len = packet_size - sizeof(mtp_data_header);
611 int buf1_len = std::max(static_cast<uint64_t>(packet_size), std::min(
612 static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length - init_read_len));
613 std::vector<char> buf1(buf1_len);
614 char *data = buf1.data();
615
616 // If necessary, allocate a second buffer for background r/w
617 int buf2_len = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE),
618 file_length - MAX_FILE_CHUNK_SIZE - init_read_len);
619 std::vector<char> buf2(std::max(0, buf2_len));
620 char *data2 = buf2.data();
621
Jerry Zhange9d94422017-01-18 12:03:56 -0800622 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
623 posix_madvise(data, buf1_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
624 posix_madvise(data2, buf2_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
625
Jerry Zhang487be612016-10-24 12:10:41 -0700626 struct aiocb aio;
627 aio.aio_fildes = mfr.fd;
628 struct aiocb *aiol[] = {&aio};
629 int ret, length;
630 bool read = false;
631 bool write = false;
632
633 // Send the header data
634 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(data);
635 header->length = __cpu_to_le32(given_length);
636 header->type = __cpu_to_le16(2); /* data packet */
637 header->command = __cpu_to_le16(mfr.command);
638 header->transaction_id = __cpu_to_le32(mfr.transaction_id);
639
640 // Some hosts don't support header/data separation even though MTP allows it
641 // Handle by filling first packet with initial file data
642 if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
643 sizeof(mtp_data_header), init_read_len, offset))
644 != init_read_len) return -1;
645 file_length -= init_read_len;
646 offset += init_read_len;
647 if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
648 if (file_length == 0) return 0;
649
Jerry Zhange9d94422017-01-18 12:03:56 -0800650 ScopedEndpointBufferAlloc scoped_alloc(mBulkIn, mMaxWrite);
Jerry Zhang5a804b92016-12-15 17:07:38 -0800651
Jerry Zhang487be612016-10-24 12:10:41 -0700652 // Break down the file into pieces that fit in buffers
653 while(file_length > 0) {
654 if (read) {
655 // Wait for the previous read to finish
656 aio_suspend(aiol, 1, nullptr);
657 ret = aio_return(&aio);
658 if (ret == -1) {
659 errno = aio_error(&aio);
660 return -1;
661 }
662 if (static_cast<size_t>(ret) < aio.aio_nbytes) {
663 errno = EIO;
664 return -1;
665 }
666
667 file_length -= ret;
668 offset += ret;
669 std::swap(data, data2);
670 read = false;
671 write = true;
672 }
673
674 if (file_length > 0) {
675 length = std::min((uint64_t) MAX_FILE_CHUNK_SIZE, file_length);
676 // Queue up another read
677 aio.aio_buf = data;
678 aio.aio_offset = offset;
679 aio.aio_nbytes = length;
680 aio_read(&aio);
681 read = true;
682 }
683
684 if (write) {
685 if (writeHandle(mBulkIn, data2, ret) == -1)
686 return -1;
687 write = false;
688 }
689 }
690
691 if (given_length == MAX_MTP_FILE_SIZE && ret % packet_size == 0) {
692 // If the last packet wasn't short, send a final empty packet
693 if (writeHandle(mBulkIn, data, 0) == -1) return -1;
694 }
695
696 return 0;
697}
698
699int MtpFfsHandle::sendEvent(mtp_event me) {
700 unsigned length = me.length;
701 int ret = writeHandle(mIntr, me.data, length);
702 return static_cast<unsigned>(ret) == length ? 0 : -1;
703}
704
705} // namespace android
706
707IMtpHandle *get_ffs_handle() {
708 return new android::MtpFfsHandle();
709}
710