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