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
This commit is contained in:
parent
0afaf7f4dd
commit
4cbf1d8822
|
@ -264,23 +264,25 @@ static void init_functionfs(struct usb_handle *h)
|
|||
{
|
||||
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 @@ 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);
|
||||
|
|
Loading…
Reference in New Issue