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

Commit 4cbf1d88 authored by Jack Pham's avatar Jack Pham
Browse files

adbd: Don't close/reopen FFS ep0 on disconnect

In case of bulk read/write failure or disconnect, transport_usb
calls usb_ffs_kick in order to force the daemon to re-open the
FunctionFS ep files as a way to soft restart the kernel driver.

However, there's no reason to always close the ep0 file, as it
would need to be reopened and the descriptors rewritten--this
is unnecessary, especially in the simple/frequent case of cable
disconnect, and causes the kernel driver to unbind and bind *all*
of the function drivers. This is causing USB Chapter 9 tests to fail.

Thus, try to reuse the same ep0 file handle across reconnects. In
case there is a failure, the ep1/ep2 opens would fail and all the
file handles get dropped. For the adb root case, the entire daemon
gets restarted anyway.

Change-Id: I0840085c52a0795dcb2d751c39aa4a436c039ee2
parent 0afaf7f4
Loading
Loading
Loading
Loading
+24 −19
Original line number Diff line number Diff line
@@ -264,6 +264,7 @@ static void init_functionfs(struct usb_handle *h)
{
    ssize_t ret;

    if (h->control < 0) { // might have already done this before
        D("OPENING %s\n", USB_FFS_ADB_EP0);
        h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
        if (h->control < 0) {
@@ -282,6 +283,7 @@ static void init_functionfs(struct usb_handle *h)
            D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno);
            goto err;
        }
    }

    h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
    if (h->bulk_out < 0) {
@@ -320,14 +322,14 @@ static void *usb_ffs_open_thread(void *x)
    while (1) {
        // wait until the USB device needs opening
        adb_mutex_lock(&usb->lock);
        while (usb->control != -1)
        while (usb->control != -1 && usb->bulk_in != -1 && usb->bulk_out != -1)
            adb_cond_wait(&usb->notify, &usb->lock);
        adb_mutex_unlock(&usb->lock);

        while (1) {
            init_functionfs(usb);

            if (usb->control >= 0)
            if (usb->control >= 0 && usb->bulk_in >= 0 && usb->bulk_out >= 0)
                break;

            adb_sleep_ms(1000);
@@ -424,10 +426,13 @@ static void usb_ffs_kick(usb_handle *h)
        D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno);

    adb_mutex_lock(&h->lock);
    adb_close(h->control);

    // don't close ep0 here, since we may not need to reinitialize it with
    // the same descriptors again. if however ep1/ep2 fail to re-open in
    // init_functionfs, only then would we close and open ep0 again.
    adb_close(h->bulk_out);
    adb_close(h->bulk_in);
    h->control = h->bulk_out = h->bulk_in = -1;
    h->bulk_out = h->bulk_in = -1;

    // notify usb_ffs_open_thread that we are disconnected
    adb_cond_signal(&h->notify);