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
diff --git a/usb_linux_client.c b/usb_linux_client.c
index fb1dad0..f20772b 100644
--- a/usb_linux_client.c
+++ b/usb_linux_client.c
@@ -264,23 +264,25 @@
 {
     ssize_t ret;
 
-    D("OPENING %s\n", USB_FFS_ADB_EP0);
-    h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
-    if (h->control < 0) {
-        D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
+    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) {
+            D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
 
-    ret = adb_write(h->control, &descriptors, sizeof(descriptors));
-    if (ret < 0) {
-        D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
+        ret = adb_write(h->control, &descriptors, sizeof(descriptors));
+        if (ret < 0) {
+            D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+            goto err;
+        }
 
-    ret = adb_write(h->control, &strings, sizeof(strings));
-    if (ret < 0) {
-        D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
+        ret = adb_write(h->control, &strings, sizeof(strings));
+        if (ret < 0) {
+            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);
@@ -320,14 +322,14 @@
     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 @@
         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);