Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b4f54266 authored by Jerry Zhang's avatar Jerry Zhang
Browse files

Retry allocations in case of ENODEV

Unlike the read() and write() calls, the ioctl() call
does not wait for endpoints to be enabled, which is
problematic if ioctls() are the first calls on the
usb connection, since they may be called before the
endpoints are set up. We'll have to retry if this
causes them to fail.

Bug: 34822471
Test: Change configs to mtp and ptp
Change-Id: I89610b9614c33f0b22535cc68cd0c9b502cb55c9
parent 4418030f
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -62,8 +62,13 @@ constexpr int MAX_FILE_CHUNK_SIZE = 3145728;
constexpr int USB_FFS_MAX_WRITE = MTP_BUFFER_SIZE;
constexpr int USB_FFS_MAX_READ = MTP_BUFFER_SIZE;

static_assert(USB_FFS_MAX_WRITE > 0, "Max r/w values must be > 0!");
static_assert(USB_FFS_MAX_READ > 0, "Max r/w values must be > 0!");

constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;

constexpr size_t ENDPOINT_ALLOC_RETRIES = 10;

struct func_desc {
    struct usb_interface_descriptor intf;
    struct usb_endpoint_descriptor_no_audio sink;
@@ -459,19 +464,28 @@ int MtpFfsHandle::start() {
    mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
    mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);

    while (mMaxWrite > USB_FFS_MAX_WRITE && mMaxRead > USB_FFS_MAX_READ) {
    size_t attempts = 0;
    while (mMaxWrite >= USB_FFS_MAX_WRITE && mMaxRead >= USB_FFS_MAX_READ &&
            attempts < ENDPOINT_ALLOC_RETRIES) {
        // If larger contiguous chunks of memory aren't available, attempt to try
        // smaller allocations.
        if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) ||
            ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) {
            if (errno == ENODEV) {
                // Driver hasn't enabled endpoints yet.
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
                attempts += 1;
                continue;
            }
            mMaxWrite /= 2;
            mMaxRead /=2;
        } else {
            return 0;
        }
    }
    // Try to start MtpServer anyway, with the smallest max r/w values
    PLOG(ERROR) << "Functionfs could not allocate any memory!";
    return -1;
    return 0;
}

int MtpFfsHandle::configure(bool usePtp) {
+4 −0
Original line number Diff line number Diff line
@@ -59,6 +59,10 @@ public:
    int sendFile(mtp_file_range mfr);
    int sendEvent(mtp_event me);

    /**
     * Open ffs endpoints and allocate necessary kernel and user memory.
     * Will sleep until endpoints are enabled, for up to 1 second.
     */
    int start();
    void close();