adb: On Mac, clear both host and device endpoints at startup

This CL clears both the host and device endpoints right at the
beginning when the bulk endpoints are identified. This is in general
a "good idea", but more specifically for us, it fixes the issue
that sometimes when adb quits, it clears the endpoint on the host,
but not on the device which resulted in a subsequent invocation of
adb was seeing a stall.

Bug: https://code.google.com/p/android/issues/detail?id=182151

Change-Id: I331fa6805c40d1f50c153c010ceecd2f6a4045eb
This commit is contained in:
Siva Velusamy 2015-08-13 08:48:06 -07:00 committed by Elliott Hughes
parent 45288223d0
commit d8b48a6281
1 changed files with 37 additions and 23 deletions

View File

@ -43,11 +43,11 @@ static io_iterator_t notificationIterator;
struct usb_handle
{
UInt8 bulkIn;
UInt8 bulkOut;
IOUSBInterfaceInterface **interface;
io_object_t usbNotification;
unsigned int zero_mask;
UInt8 bulkIn;
UInt8 bulkOut;
IOUSBInterfaceInterface190** interface;
io_object_t usbNotification;
unsigned int zero_mask;
};
static CFRunLoopRef currentRunLoop = 0;
@ -59,7 +59,7 @@ static void AndroidInterfaceAdded(void *refCon, io_iterator_t iterator);
static void AndroidInterfaceNotify(void *refCon, io_iterator_t iterator,
natural_t messageType,
void *messageArgument);
static usb_handle* CheckInterface(IOUSBInterfaceInterface **iface,
static usb_handle* CheckInterface(IOUSBInterfaceInterface190 **iface,
UInt16 vendor, UInt16 product);
static int
@ -256,7 +256,7 @@ AndroidInterfaceAdded(void *refCon, io_iterator_t iterator)
DBG("INFO: Found vid=%04x pid=%04x serial=%s\n", vendor, product,
serial);
usb_handle* handle = CheckInterface((IOUSBInterfaceInterface**)iface,
usb_handle* handle = CheckInterface((IOUSBInterfaceInterface190**)iface,
vendor, product);
if (handle == NULL) {
DBG("ERR: Could not find device interface: %08x\n", kr);
@ -299,10 +299,22 @@ AndroidInterfaceNotify(void *refCon, io_service_t service, natural_t messageType
}
}
// Used to clear both the endpoints before starting.
// When adb quits, we might clear the host endpoint but not the device.
// So we make sure both sides are clear before starting up.
static bool ClearPipeStallBothEnds(IOUSBInterfaceInterface190** interface, UInt8 bulkEp) {
IOReturn rc = (*interface)->ClearPipeStallBothEnds(interface, bulkEp);
if (rc != kIOReturnSuccess) {
DBG("ERR: Could not clear pipe: (%08x)\n", rc);
return false;
}
return true;
}
//* TODO: simplify this further since we only register to get ADB interface
//* subclass+protocol events
static usb_handle*
CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 product)
CheckInterface(IOUSBInterfaceInterface190 **interface, UInt16 vendor, UInt16 product)
{
usb_handle* handle = NULL;
IOReturn kr;
@ -335,9 +347,9 @@ CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 produc
//* check to make sure interface class, subclass and protocol match ADB
//* avoid opening mass storage endpoints
if (!is_adb_interface(vendor, product, interfaceClass,
interfaceSubClass, interfaceProtocol))
if (!is_adb_interface(vendor, product, interfaceClass, interfaceSubClass, interfaceProtocol)) {
goto err_bad_adb_interface;
}
handle = reinterpret_cast<usb_handle*>(calloc(1, sizeof(usb_handle)));
if (handle == nullptr) goto err_bad_adb_interface;
@ -353,22 +365,24 @@ CheckInterface(IOUSBInterfaceInterface **interface, UInt16 vendor, UInt16 produc
kr = (*interface)->GetPipeProperties(interface, endpoint, &direction,
&number, &transferType, &maxPacketSize, &interval);
if (kIOReturnSuccess == kr) {
if (kUSBBulk != transferType)
continue;
if (kUSBIn == direction)
handle->bulkIn = endpoint;
if (kUSBOut == direction)
handle->bulkOut = endpoint;
handle->zero_mask = maxPacketSize - 1;
} else {
if (kr != kIOReturnSuccess) {
DBG("ERR: FindDeviceInterface - could not get pipe properties (%08x)\n", kr);
goto err_get_pipe_props;
}
if (kUSBBulk != transferType) continue;
if (kUSBIn == direction) {
handle->bulkIn = endpoint;
if (!ClearPipeStallBothEnds(interface, handle->bulkIn)) goto err_get_pipe_props;
}
if (kUSBOut == direction) {
handle->bulkOut = endpoint;
if (!ClearPipeStallBothEnds(interface, handle->bulkOut)) goto err_get_pipe_props;
}
handle->zero_mask = maxPacketSize - 1;
}
handle->interface = interface;