blob: 10314e9f835246b3a164024bf03044d0918efe23 [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
41namespace {
42
43constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
44constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
45constexpr char FFS_MTP_EP_INTR[] = "/dev/usb-ffs/mtp/ep3";
46
47constexpr int MAX_PACKET_SIZE_FS = 64;
48constexpr int MAX_PACKET_SIZE_HS = 512;
49constexpr int MAX_PACKET_SIZE_SS = 1024;
50
51// Must be divisible by all max packet size values
52constexpr int MAX_FILE_CHUNK_SIZE = 3145728;
53
54// Safe values since some devices cannot handle large DMAs
55// To get good performance, override these with
56// higher values per device using the properties
57// sys.usb.ffs.max_read and sys.usb.ffs.max_write
58constexpr int USB_FFS_MAX_WRITE = 32768;
59constexpr int USB_FFS_MAX_READ = 32768;
60
61constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;
62
63struct func_desc {
64 struct usb_interface_descriptor intf;
65 struct usb_endpoint_descriptor_no_audio sink;
66 struct usb_endpoint_descriptor_no_audio source;
67 struct usb_endpoint_descriptor_no_audio intr;
68} __attribute__((packed));
69
70struct ss_func_desc {
71 struct usb_interface_descriptor intf;
72 struct usb_endpoint_descriptor_no_audio sink;
73 struct usb_ss_ep_comp_descriptor sink_comp;
74 struct usb_endpoint_descriptor_no_audio source;
75 struct usb_ss_ep_comp_descriptor source_comp;
76 struct usb_endpoint_descriptor_no_audio intr;
77 struct usb_ss_ep_comp_descriptor intr_comp;
78} __attribute__((packed));
79
80struct desc_v1 {
81 struct usb_functionfs_descs_head_v1 {
82 __le32 magic;
83 __le32 length;
84 __le32 fs_count;
85 __le32 hs_count;
86 } __attribute__((packed)) header;
87 struct func_desc fs_descs, hs_descs;
88} __attribute__((packed));
89
90struct desc_v2 {
91 struct usb_functionfs_descs_head_v2 header;
92 // The rest of the structure depends on the flags in the header.
93 __le32 fs_count;
94 __le32 hs_count;
95 __le32 ss_count;
96 struct func_desc fs_descs, hs_descs;
97 struct ss_func_desc ss_descs;
98} __attribute__((packed));
99
100const struct usb_interface_descriptor mtp_interface_desc = {
101 .bLength = USB_DT_INTERFACE_SIZE,
102 .bDescriptorType = USB_DT_INTERFACE,
103 .bInterfaceNumber = 0,
104 .bNumEndpoints = 3,
105 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
106 .bInterfaceSubClass = 1,
107 .bInterfaceProtocol = 1,
108};
109
110const struct usb_interface_descriptor ptp_interface_desc = {
111 .bLength = USB_DT_INTERFACE_SIZE,
112 .bDescriptorType = USB_DT_INTERFACE,
113 .bInterfaceNumber = 0,
114 .bNumEndpoints = 3,
115 .bInterfaceClass = USB_CLASS_STILL_IMAGE,
116 .bInterfaceSubClass = 1,
117 .bInterfaceProtocol = 1,
118};
119
120const struct usb_endpoint_descriptor_no_audio fs_sink = {
121 .bLength = USB_DT_ENDPOINT_SIZE,
122 .bDescriptorType = USB_DT_ENDPOINT,
123 .bEndpointAddress = 1 | USB_DIR_IN,
124 .bmAttributes = USB_ENDPOINT_XFER_BULK,
125 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
126};
127
128const struct usb_endpoint_descriptor_no_audio fs_source = {
129 .bLength = USB_DT_ENDPOINT_SIZE,
130 .bDescriptorType = USB_DT_ENDPOINT,
131 .bEndpointAddress = 2 | USB_DIR_OUT,
132 .bmAttributes = USB_ENDPOINT_XFER_BULK,
133 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
134};
135
136const struct usb_endpoint_descriptor_no_audio fs_intr = {
137 .bLength = USB_DT_ENDPOINT_SIZE,
138 .bDescriptorType = USB_DT_ENDPOINT,
139 .bEndpointAddress = 3 | USB_DIR_IN,
140 .bmAttributes = USB_ENDPOINT_XFER_INT,
141 .wMaxPacketSize = MAX_PACKET_SIZE_FS,
142 .bInterval = 6,
143};
144
145const struct usb_endpoint_descriptor_no_audio hs_sink = {
146 .bLength = USB_DT_ENDPOINT_SIZE,
147 .bDescriptorType = USB_DT_ENDPOINT,
148 .bEndpointAddress = 1 | USB_DIR_IN,
149 .bmAttributes = USB_ENDPOINT_XFER_BULK,
150 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
151};
152
153const struct usb_endpoint_descriptor_no_audio hs_source = {
154 .bLength = USB_DT_ENDPOINT_SIZE,
155 .bDescriptorType = USB_DT_ENDPOINT,
156 .bEndpointAddress = 2 | USB_DIR_OUT,
157 .bmAttributes = USB_ENDPOINT_XFER_BULK,
158 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
159};
160
161const struct usb_endpoint_descriptor_no_audio hs_intr = {
162 .bLength = USB_DT_ENDPOINT_SIZE,
163 .bDescriptorType = USB_DT_ENDPOINT,
164 .bEndpointAddress = 3 | USB_DIR_IN,
165 .bmAttributes = USB_ENDPOINT_XFER_INT,
166 .wMaxPacketSize = MAX_PACKET_SIZE_HS,
167 .bInterval = 6,
168};
169
170const struct usb_endpoint_descriptor_no_audio ss_sink = {
171 .bLength = USB_DT_ENDPOINT_SIZE,
172 .bDescriptorType = USB_DT_ENDPOINT,
173 .bEndpointAddress = 1 | USB_DIR_IN,
174 .bmAttributes = USB_ENDPOINT_XFER_BULK,
175 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
176};
177
178const struct usb_endpoint_descriptor_no_audio ss_source = {
179 .bLength = USB_DT_ENDPOINT_SIZE,
180 .bDescriptorType = USB_DT_ENDPOINT,
181 .bEndpointAddress = 2 | USB_DIR_OUT,
182 .bmAttributes = USB_ENDPOINT_XFER_BULK,
183 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
184};
185
186const struct usb_endpoint_descriptor_no_audio ss_intr = {
187 .bLength = USB_DT_ENDPOINT_SIZE,
188 .bDescriptorType = USB_DT_ENDPOINT,
189 .bEndpointAddress = 3 | USB_DIR_IN,
190 .bmAttributes = USB_ENDPOINT_XFER_INT,
191 .wMaxPacketSize = MAX_PACKET_SIZE_SS,
192 .bInterval = 6,
193};
194
195const struct usb_ss_ep_comp_descriptor ss_sink_comp = {
196 .bLength = sizeof(ss_sink_comp),
197 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
198 .bMaxBurst = 2,
199};
200
201const struct usb_ss_ep_comp_descriptor ss_source_comp = {
202 .bLength = sizeof(ss_source_comp),
203 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
204 .bMaxBurst = 2,
205};
206
207const struct usb_ss_ep_comp_descriptor ss_intr_comp = {
208 .bLength = sizeof(ss_intr_comp),
209 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
210};
211
212const struct func_desc mtp_fs_descriptors = {
213 .intf = mtp_interface_desc,
214 .sink = fs_sink,
215 .source = fs_source,
216 .intr = fs_intr,
217};
218
219const struct func_desc mtp_hs_descriptors = {
220 .intf = mtp_interface_desc,
221 .sink = hs_sink,
222 .source = hs_source,
223 .intr = hs_intr,
224};
225
226const struct ss_func_desc mtp_ss_descriptors = {
227 .intf = mtp_interface_desc,
228 .sink = ss_sink,
229 .sink_comp = ss_sink_comp,
230 .source = ss_source,
231 .source_comp = ss_source_comp,
232 .intr = ss_intr,
233 .intr_comp = ss_intr_comp,
234};
235
236const struct func_desc ptp_fs_descriptors = {
237 .intf = ptp_interface_desc,
238 .sink = fs_sink,
239 .source = fs_source,
240 .intr = fs_intr,
241};
242
243const struct func_desc ptp_hs_descriptors = {
244 .intf = ptp_interface_desc,
245 .sink = hs_sink,
246 .source = hs_source,
247 .intr = hs_intr,
248};
249
250const struct ss_func_desc ptp_ss_descriptors = {
251 .intf = ptp_interface_desc,
252 .sink = ss_sink,
253 .sink_comp = ss_sink_comp,
254 .source = ss_source,
255 .source_comp = ss_source_comp,
256 .intr = ss_intr,
257 .intr_comp = ss_intr_comp,
258};
259
260const struct {
261 struct usb_functionfs_strings_head header;
262} __attribute__((packed)) strings = {
263 .header = {
264 .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
265 .length = cpu_to_le32(sizeof(strings)),
266 .str_count = cpu_to_le32(0),
267 .lang_count = cpu_to_le32(0),
268 },
269};
270
271} // anonymous namespace
272
273namespace android {
274
275MtpFfsHandle::MtpFfsHandle() :
276 mMaxWrite(USB_FFS_MAX_WRITE),
277 mMaxRead(USB_FFS_MAX_READ) {}
278
279MtpFfsHandle::~MtpFfsHandle() {}
280
281void MtpFfsHandle::closeEndpoints() {
282 mIntr.reset();
283 mBulkIn.reset();
284 mBulkOut.reset();
285}
286
287bool MtpFfsHandle::initFunctionfs() {
288 ssize_t ret;
289 struct desc_v1 v1_descriptor;
290 struct desc_v2 v2_descriptor;
291
292 v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
293 v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
294 v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC |
295 FUNCTIONFS_HAS_SS_DESC;
296 v2_descriptor.fs_count = 4;
297 v2_descriptor.hs_count = 4;
298 v2_descriptor.ss_count = 7;
299 v2_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
300 v2_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
301 v2_descriptor.ss_descs = mPtp ? ptp_ss_descriptors : mtp_ss_descriptors;
302
303 if (mControl < 0) { // might have already done this before
304 mControl.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP0, O_RDWR)));
305 if (mControl < 0) {
306 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open control endpoint";
307 goto err;
308 }
309
310 ret = TEMP_FAILURE_RETRY(::write(mControl, &v2_descriptor, sizeof(v2_descriptor)));
311 if (ret < 0) {
312 v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
313 v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
314 v1_descriptor.header.fs_count = 4;
315 v1_descriptor.header.hs_count = 4;
316 v1_descriptor.fs_descs = mPtp ? ptp_fs_descriptors : mtp_fs_descriptors;
317 v1_descriptor.hs_descs = mPtp ? ptp_hs_descriptors : mtp_hs_descriptors;
318 PLOG(ERROR) << FFS_MTP_EP0 << "Switching to V1 descriptor format";
319 ret = TEMP_FAILURE_RETRY(::write(mControl, &v1_descriptor, sizeof(v1_descriptor)));
320 if (ret < 0) {
321 PLOG(ERROR) << FFS_MTP_EP0 << "Writing descriptors failed";
322 goto err;
323 }
324 }
325 ret = TEMP_FAILURE_RETRY(::write(mControl, &strings, sizeof(strings)));
326 if (ret < 0) {
327 PLOG(ERROR) << FFS_MTP_EP0 << "Writing strings failed";
328 goto err;
329 }
330 }
331 if (mBulkIn > -1 || mBulkOut > -1 || mIntr > -1)
332 LOG(WARNING) << "Endpoints were not closed before configure!";
333
334 mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
335 if (mBulkIn < 0) {
336 PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
337 goto err;
338 }
339
340 mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
341 if (mBulkOut < 0) {
342 PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
343 goto err;
344 }
345
346 mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
347 if (mIntr < 0) {
348 PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
349 goto err;
350 }
351
352 return true;
353
354err:
355 closeEndpoints();
356 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();
437 return 0;
438}
439
440int MtpFfsHandle::configure(bool usePtp) {
441 // Wait till previous server invocation has closed
442 std::lock_guard<std::mutex> lk(mLock);
443
444 // If ptp is changed, the configuration must be rewritten
445 if (mPtp != usePtp) {
446 closeEndpoints();
447 closeConfig();
448 }
449 mPtp = usePtp;
450
451 if (!initFunctionfs()) {
452 return -1;
453 }
454
455 // Get device specific r/w size
456 mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", 0);
457 mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", 0);
458 if (!mMaxWrite)
459 mMaxWrite = USB_FFS_MAX_WRITE;
460 if (!mMaxRead)
461 mMaxRead = USB_FFS_MAX_READ;
462 return 0;
463}
464
465void MtpFfsHandle::close() {
466 closeEndpoints();
467 mLock.unlock();
468}
469
470/* Read from USB and write to a local file. */
471int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
472 // When receiving files, the incoming length is given in 32 bits.
473 // A >4G file is given as 0xFFFFFFFF
474 uint32_t file_length = mfr.length;
475 uint64_t offset = lseek(mfr.fd, 0, SEEK_CUR);
476
477 int buf1_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
478 std::vector<char> buf1(buf1_len);
479 char* data = buf1.data();
480
481 // If necessary, allocate a second buffer for background r/w
482 int buf2_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE),
483 file_length - MAX_FILE_CHUNK_SIZE);
484 std::vector<char> buf2(std::max(0, buf2_len));
485 char *data2 = buf2.data();
486
487 struct aiocb aio;
488 aio.aio_fildes = mfr.fd;
489 aio.aio_buf = nullptr;
490 struct aiocb *aiol[] = {&aio};
491 int ret;
492 size_t length;
493 bool read = false;
494 bool write = false;
495
496 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
497
498 // Break down the file into pieces that fit in buffers
499 while (file_length > 0 || write) {
500 if (file_length > 0) {
501 length = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
502
503 // Read data from USB
504 if ((ret = readHandle(mBulkOut, data, length)) == -1) {
505 return -1;
506 }
507
508 if (file_length != MAX_MTP_FILE_SIZE && ret < static_cast<int>(length)) {
509 errno = EIO;
510 return -1;
511 }
512 read = true;
513 }
514
515 if (write) {
516 // get the return status of the last write request
517 aio_suspend(aiol, 1, nullptr);
518
519 int written = aio_return(&aio);
520 if (written == -1) {
521 errno = aio_error(&aio);
522 return -1;
523 }
524 if (static_cast<size_t>(written) < aio.aio_nbytes) {
525 errno = EIO;
526 return -1;
527 }
528 write = false;
529 }
530
531 if (read) {
532 // Enqueue a new write request
533 aio.aio_buf = data;
534 aio.aio_sink = mfr.fd;
535 aio.aio_offset = offset;
536 aio.aio_nbytes = ret;
537 aio_write(&aio);
538
539 if (file_length == MAX_MTP_FILE_SIZE) {
540 // For larger files, receive until a short packet is received.
541 if (static_cast<size_t>(ret) < length) {
542 file_length = 0;
543 }
544 } else {
545 file_length -= ret;
546 }
547
548 offset += ret;
549 std::swap(data, data2);
550
551 write = true;
552 read = false;
553 }
554 }
555 return 0;
556}
557
558/* Read from a local file and send over USB. */
559int MtpFfsHandle::sendFile(mtp_file_range mfr) {
560 uint64_t file_length = mfr.length;
561 uint32_t given_length = std::min(static_cast<uint64_t>(MAX_MTP_FILE_SIZE),
562 file_length + sizeof(mtp_data_header));
563 uint64_t offset = 0;
564 struct usb_endpoint_descriptor mBulkIn_desc;
565 int packet_size;
566
567 if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_DESC, reinterpret_cast<unsigned long>(&mBulkIn_desc))) {
568 PLOG(ERROR) << "Could not get FFS bulk-in descriptor";
569 packet_size = MAX_PACKET_SIZE_HS;
570 } else {
571 packet_size = mBulkIn_desc.wMaxPacketSize;
572 }
573
574 posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
575
576 int init_read_len = packet_size - sizeof(mtp_data_header);
577 int buf1_len = std::max(static_cast<uint64_t>(packet_size), std::min(
578 static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length - init_read_len));
579 std::vector<char> buf1(buf1_len);
580 char *data = buf1.data();
581
582 // If necessary, allocate a second buffer for background r/w
583 int buf2_len = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE),
584 file_length - MAX_FILE_CHUNK_SIZE - init_read_len);
585 std::vector<char> buf2(std::max(0, buf2_len));
586 char *data2 = buf2.data();
587
588 struct aiocb aio;
589 aio.aio_fildes = mfr.fd;
590 struct aiocb *aiol[] = {&aio};
591 int ret, length;
592 bool read = false;
593 bool write = false;
594
595 // Send the header data
596 mtp_data_header *header = reinterpret_cast<mtp_data_header*>(data);
597 header->length = __cpu_to_le32(given_length);
598 header->type = __cpu_to_le16(2); /* data packet */
599 header->command = __cpu_to_le16(mfr.command);
600 header->transaction_id = __cpu_to_le32(mfr.transaction_id);
601
602 // Some hosts don't support header/data separation even though MTP allows it
603 // Handle by filling first packet with initial file data
604 if (TEMP_FAILURE_RETRY(pread(mfr.fd, reinterpret_cast<char*>(data) +
605 sizeof(mtp_data_header), init_read_len, offset))
606 != init_read_len) return -1;
607 file_length -= init_read_len;
608 offset += init_read_len;
609 if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
610 if (file_length == 0) return 0;
611
612 // Break down the file into pieces that fit in buffers
613 while(file_length > 0) {
614 if (read) {
615 // Wait for the previous read to finish
616 aio_suspend(aiol, 1, nullptr);
617 ret = aio_return(&aio);
618 if (ret == -1) {
619 errno = aio_error(&aio);
620 return -1;
621 }
622 if (static_cast<size_t>(ret) < aio.aio_nbytes) {
623 errno = EIO;
624 return -1;
625 }
626
627 file_length -= ret;
628 offset += ret;
629 std::swap(data, data2);
630 read = false;
631 write = true;
632 }
633
634 if (file_length > 0) {
635 length = std::min((uint64_t) MAX_FILE_CHUNK_SIZE, file_length);
636 // Queue up another read
637 aio.aio_buf = data;
638 aio.aio_offset = offset;
639 aio.aio_nbytes = length;
640 aio_read(&aio);
641 read = true;
642 }
643
644 if (write) {
645 if (writeHandle(mBulkIn, data2, ret) == -1)
646 return -1;
647 write = false;
648 }
649 }
650
651 if (given_length == MAX_MTP_FILE_SIZE && ret % packet_size == 0) {
652 // If the last packet wasn't short, send a final empty packet
653 if (writeHandle(mBulkIn, data, 0) == -1) return -1;
654 }
655
656 return 0;
657}
658
659int MtpFfsHandle::sendEvent(mtp_event me) {
660 unsigned length = me.length;
661 int ret = writeHandle(mIntr, me.data, length);
662 return static_cast<unsigned>(ret) == length ? 0 : -1;
663}
664
665} // namespace android
666
667IMtpHandle *get_ffs_handle() {
668 return new android::MtpFfsHandle();
669}
670