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

Commit 8bf37d7a authored by Josh Gao's avatar Josh Gao
Browse files

adb: properly handle libusb_clear_halt failure.

The original code used continue to attempt to try to skip the current
device, but there was an loop between the outside one and the continue.
Move the device handling logic into a function and replace continue
with return.

Test: mma
Change-Id: Iaa7f4b5ddc26d2ce03f1172d37d6307190b44412
parent 5b8a92af
Loading
Loading
Loading
Loading
+180 −180
Original line number Diff line number Diff line
@@ -184,16 +184,7 @@ static bool should_perform_zero_transfer(uint8_t endpoint, size_t write_length,
           (write_length & zero_mask) == 0;
}

static void poll_for_devices() {
    libusb_device** list;
    adb_thread_setname("device poll");
    while (!terminate_device_poll_thread) {
        const ssize_t device_count = libusb_get_device_list(nullptr, &list);

        LOG(VERBOSE) << "found " << device_count << " attached devices";

        for (ssize_t i = 0; i < device_count; ++i) {
            libusb_device* device = list[i];
static void process_device(libusb_device* device) {
    std::string device_address = get_device_address(device);
    std::string device_serial;

@@ -201,23 +192,24 @@ static void poll_for_devices() {
    libusb_device_descriptor device_desc;
    int rc = libusb_get_device_descriptor(device, &device_desc);
    if (rc != 0) {
                LOG(WARNING) << "failed to get device descriptor for device at " << device_address
                             << ": " << libusb_error_name(rc);
        LOG(WARNING) << "failed to get device descriptor for device at " << device_address << ": "
                     << libusb_error_name(rc);
        return;
    }

    if (device_desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) {
        // Assume that all Android devices have the device class set to per interface.
        // TODO: Is this assumption valid?
        LOG(VERBOSE) << "skipping device with incorrect class at " << device_address;
                continue;
        return;
    }

    libusb_config_descriptor* config_raw;
    rc = libusb_get_active_config_descriptor(device, &config_raw);
    if (rc != 0) {
                LOG(WARNING) << "failed to get active config descriptor for device at "
                             << device_address << ": " << libusb_error_name(rc);
                continue;
        LOG(WARNING) << "failed to get active config descriptor for device at " << device_address
                     << ": " << libusb_error_name(rc);
        return;
    }
    const unique_config_descriptor config(config_raw);

@@ -233,27 +225,25 @@ static void poll_for_devices() {
        if (interface.num_altsetting != 1) {
            // Assume that interfaces with alternate settings aren't adb interfaces.
            // TODO: Is this assumption valid?
                    LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at "
                                 << device_address << " (interface " << interface_num << ")";
                    continue;
            LOG(VERBOSE) << "skipping interface with incorrect num_altsetting at " << device_address
                         << " (interface " << interface_num << ")";
            return;
        }

        const libusb_interface_descriptor& interface_desc = interface.altsetting[0];
                if (!is_adb_interface(interface_desc.bInterfaceClass,
                                      interface_desc.bInterfaceSubClass,
        if (!is_adb_interface(interface_desc.bInterfaceClass, interface_desc.bInterfaceSubClass,
                              interface_desc.bInterfaceProtocol)) {
                    LOG(VERBOSE) << "skipping non-adb interface at " << device_address
                                 << " (interface " << interface_num << ")";
                    continue;
            LOG(VERBOSE) << "skipping non-adb interface at " << device_address << " (interface "
                         << interface_num << ")";
            return;
        }

                LOG(VERBOSE) << "found potential adb interface at " << device_address
                             << " (interface " << interface_num << ")";
        LOG(VERBOSE) << "found potential adb interface at " << device_address << " (interface "
                     << interface_num << ")";

        bool found_in = false;
        bool found_out = false;
                for (size_t endpoint_num = 0; endpoint_num < interface_desc.bNumEndpoints;
                     ++endpoint_num) {
        for (size_t endpoint_num = 0; endpoint_num < interface_desc.bNumEndpoints; ++endpoint_num) {
            const auto& endpoint_desc = interface_desc.endpoint[endpoint_num];
            const uint8_t endpoint_addr = endpoint_desc.bEndpointAddress;
            const uint8_t endpoint_attr = endpoint_desc.bmAttributes;
@@ -261,7 +251,7 @@ static void poll_for_devices() {
            const uint8_t transfer_type = endpoint_attr & LIBUSB_TRANSFER_TYPE_MASK;

            if (transfer_type != LIBUSB_TRANSFER_TYPE_BULK) {
                        continue;
                return;
            }

            if (endpoint_is_output(endpoint_addr) && !found_out) {
@@ -288,14 +278,13 @@ static void poll_for_devices() {
        } else {
            LOG(VERBOSE) << "rejecting potential adb interface at " << device_address
                         << "(interface " << interface_num << "): missing bulk endpoints "
                                 << "(found_in = " << found_in << ", found_out = " << found_out
                                 << ")";
                         << "(found_in = " << found_in << ", found_out = " << found_out << ")";
        }
    }

    if (!found_adb) {
        LOG(VERBOSE) << "skipping device with no adb interfaces at " << device_address;
                continue;
        return;
    }

    {
@@ -303,7 +292,7 @@ static void poll_for_devices() {
        if (usb_handles.find(device_address) != usb_handles.end()) {
            LOG(VERBOSE) << "device at " << device_address
                         << " has already been registered, skipping";
                    continue;
            return;
        }
    }

@@ -316,25 +305,25 @@ static void poll_for_devices() {
                   << StringPrintf("bulk_in = %#x, bulk_out = %#x", bulk_in, bulk_out);

        device_serial.resize(255);
                rc = libusb_get_string_descriptor_ascii(
                    handle_raw, device_desc.iSerialNumber,
                    reinterpret_cast<unsigned char*>(&device_serial[0]), device_serial.length());
        rc = libusb_get_string_descriptor_ascii(handle_raw, device_desc.iSerialNumber,
                                                reinterpret_cast<unsigned char*>(&device_serial[0]),
                                                device_serial.length());
        if (rc == 0) {
            LOG(WARNING) << "received empty serial from device at " << device_address;
                    continue;
            return;
        } else if (rc < 0) {
            LOG(WARNING) << "failed to get serial from device at " << device_address
                         << libusb_error_name(rc);
                    continue;
            return;
        }
        device_serial.resize(rc);

        // WARNING: this isn't released via RAII.
        rc = libusb_claim_interface(handle.get(), interface_num);
        if (rc != 0) {
                    LOG(WARNING) << "failed to claim adb interface for device '" << device_serial
                                 << "'" << libusb_error_name(rc);
                    continue;
            LOG(WARNING) << "failed to claim adb interface for device '" << device_serial << "'"
                         << libusb_error_name(rc);
            return;
        }

        for (uint8_t endpoint : {bulk_in, bulk_out}) {
@@ -344,7 +333,7 @@ static void poll_for_devices() {
                             << "' endpoint 0x" << std::hex << endpoint << ": "
                             << libusb_error_name(rc);
                libusb_release_interface(handle.get(), interface_num);
                        continue;
                return;
            }
        }
    } else {
@@ -355,8 +344,7 @@ static void poll_for_devices() {
#if defined(__linux__)
        // libusb doesn't think we should be messing around with devices we don't have
        // write access to, but Linux at least lets us get the serial number anyway.
                if (!android::base::ReadFileToString(get_device_serial_path(device),
                                                     &device_serial)) {
        if (!android::base::ReadFileToString(get_device_serial_path(device), &device_serial)) {
            // We don't actually want to treat an unknown serial as an error because
            // devices aren't able to communicate a serial number in early bringup.
            // http://b/20883914
@@ -366,13 +354,13 @@ static void poll_for_devices() {
#else
        // On Mac OS and Windows, we're screwed. But I don't think this situation actually
        // happens on those OSes.
                continue;
        return;
#endif
    }

            auto result = std::make_unique<usb_handle>(device_address, device_serial,
                                                       std::move(handle), interface_num, bulk_in,
                                                       bulk_out, zero_mask, packet_size);
    auto result =
        std::make_unique<usb_handle>(device_address, device_serial, std::move(handle),
                                     interface_num, bulk_in, bulk_out, zero_mask, packet_size);
    usb_handle* usb_handle_raw = result.get();

    {
@@ -380,11 +368,23 @@ static void poll_for_devices() {
        usb_handles[device_address] = std::move(result);
    }

            register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(),
                                   writable);
    register_usb_transport(usb_handle_raw, device_serial.c_str(), device_address.c_str(), writable);

    LOG(INFO) << "registered new usb device '" << device_serial << "'";
}

static void poll_for_devices() {
    libusb_device** list;
    adb_thread_setname("device poll");
    while (!terminate_device_poll_thread) {
        const ssize_t device_count = libusb_get_device_list(nullptr, &list);

        LOG(VERBOSE) << "found " << device_count << " attached devices";

        for (ssize_t i = 0; i < device_count; ++i) {
            process_device(list[i]);
        }

        libusb_free_device_list(list, 1);

        adb_notify_device_scan_complete();