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