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

Commit 9425996b authored by Josh Gao's avatar Josh Gao
Browse files

adb: get libusb compiling on Windows.

This still doesn't work yet because libusb doesn't support hotplug on
Windows yet, but it's in the milestones for the next libusb release,
and this is enough to start poking around with the WinUSB device-side
stuff, so leave it broken for now.

Bug: http://b/68993980
Test: set ADB_LIBUSB=1; adb.exe server nodaemon aborts in the expected place
Change-Id: Icef7d46e31c847d6a8e724c6f58ae5db43673c16
parent cce381e3
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -101,6 +101,8 @@ LIBADB_windows_SRC_FILES := \
    sysdeps_win32.cpp \
    sysdeps/win32/errno.cpp \
    sysdeps/win32/stat.cpp \
    client/usb_dispatch.cpp \
    client/usb_libusb.cpp \
    client/usb_windows.cpp \

LIBADB_TEST_windows_SRCS := \
@@ -159,9 +161,7 @@ LOCAL_SANITIZE := $(adb_host_sanitize)

# Even though we're building a static library (and thus there's no link step for
# this to take effect), this adds the includes to our path.
LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd
LOCAL_STATIC_LIBRARIES_linux := libusb
LOCAL_STATIC_LIBRARIES_darwin := libusb
LOCAL_STATIC_LIBRARIES := libcrypto_utils libcrypto libbase libmdnssd libusb

LOCAL_C_INCLUDES_windows := development/host/windows/usb/api/
LOCAL_MULTILIB := first
@@ -230,9 +230,7 @@ LOCAL_STATIC_LIBRARIES := \
    libdiagnose_usb \
    libmdnssd \
    libgmock_host \

LOCAL_STATIC_LIBRARIES_linux := libusb
LOCAL_STATIC_LIBRARIES_darwin := libusb
    libusb \

# Set entrypoint to wmain from sysdeps_win32.cpp instead of main
LOCAL_LDFLAGS_windows := -municode
@@ -298,14 +296,12 @@ LOCAL_STATIC_LIBRARIES := \
    libdiagnose_usb \
    liblog \
    libmdnssd \
    libusb \

# Don't use libcutils on Windows.
LOCAL_STATIC_LIBRARIES_darwin := libcutils
LOCAL_STATIC_LIBRARIES_linux := libcutils

LOCAL_STATIC_LIBRARIES_darwin += libusb
LOCAL_STATIC_LIBRARIES_linux += libusb

LOCAL_CXX_STL := libc++_static

# Don't add anything here, we don't want additional shared dependencies
+50 −51
Original line number Diff line number Diff line
@@ -41,8 +41,6 @@
#include "transport.h"
#include "usb.h"

using namespace std::literals;

using android::base::StringPrintf;

// RAII wrappers for libusb.
@@ -222,7 +220,7 @@ static void process_device(libusb_device* device) {

    // Use size_t for interface_num so <iostream>s don't mangle it.
    size_t interface_num;
    uint16_t zero_mask;
    uint16_t zero_mask = 0;
    uint8_t bulk_in = 0, bulk_out = 0;
    size_t packet_size = 0;
    bool found_adb = false;
@@ -372,9 +370,9 @@ static void process_device(libusb_device* device) {
#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);
    std::unique_ptr<usb_handle> result(new 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();

    {
@@ -397,7 +395,7 @@ static void device_connected(libusb_device* device) {
    // hack around this by inserting a sleep.
    auto thread = std::thread([device]() {
        std::string device_path = get_device_dev_path(device);
        std::this_thread::sleep_for(1s);
        std::this_thread::sleep_for(std::chrono::seconds(1));

        process_device(device);
        if (--connecting_devices == 0) {
@@ -448,8 +446,8 @@ static void hotplug_thread() {
    }
}

static int hotplug_callback(libusb_context*, libusb_device* device, libusb_hotplug_event event,
                            void*) {
static LIBUSB_CALL int hotplug_callback(libusb_context*, libusb_device* device,
                                        libusb_hotplug_event event, void*) {
    // We're called with the libusb lock taken. Call these on a separate thread outside of this
    // function so that the usb_handle mutex is always taken before the libusb mutex.
    static std::once_flag once;
@@ -493,13 +491,7 @@ void usb_cleanup() {
    libusb_hotplug_deregister_callback(nullptr, hotplug_handle);
}

// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
static int perform_usb_transfer(usb_handle* h, transfer_info* info,
                                std::unique_lock<std::mutex> device_lock) {
    libusb_transfer* transfer = info->transfer;

    transfer->user_data = info;
    transfer->callback = [](libusb_transfer* transfer) {
static LIBUSB_CALL void transfer_callback(libusb_transfer* transfer) {
    transfer_info* info = static_cast<transfer_info*>(transfer->user_data);

    LOG(DEBUG) << info->name << " transfer callback entered";
@@ -510,8 +502,7 @@ static int perform_usb_transfer(usb_handle* h, transfer_info* info,
    LOG(DEBUG) << info->name << " callback successfully acquired lock";

    if (transfer->status != LIBUSB_TRANSFER_COMPLETED) {
            LOG(WARNING) << info->name
                         << " transfer failed: " << libusb_error_name(transfer->status);
        LOG(WARNING) << info->name << " transfer failed: " << libusb_error_name(transfer->status);
        info->Notify();
        return;
    }
@@ -545,7 +536,15 @@ static int perform_usb_transfer(usb_handle* h, transfer_info* info,

    LOG(VERBOSE) << info->name << "transfer fully complete";
    info->Notify();
    };
}

// Dispatch a libusb transfer, unlock |device_lock|, and then wait for the result.
static int perform_usb_transfer(usb_handle* h, transfer_info* info,
                                std::unique_lock<std::mutex> device_lock) {
    libusb_transfer* transfer = info->transfer;

    transfer->user_data = info;
    transfer->callback = transfer_callback;

    LOG(DEBUG) << "locking " << info->name << " transfer_info mutex";
    std::unique_lock<std::mutex> lock(info->mutex);
+12 −29
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <stdio.h>
#include <stdlib.h>

#include <algorithm>
#include <mutex>
#include <thread>

@@ -40,6 +41,8 @@
#include "sysdeps/chrono.h"
#include "transport.h"

namespace native {

/** Structure usb_handle describes our connection to the usb device via
  AdbWinApi.dll. This structure is returned from usb_open() routine and
  is expected in each subsequent call that is accessing the device.
@@ -48,13 +51,7 @@
  rely on AdbWinApi.dll's handle validation and AdbCloseHandle(endpoint)'s
  ability to break a thread out of pipe IO.
*/
struct usb_handle {
    /// Previous entry in the list of opened usb handles
    usb_handle* prev;

    /// Next entry in the list of opened usb handles
    usb_handle* next;

struct usb_handle : public ::usb_handle {
    /// Handle to USB interface
    ADBAPIHANDLE adb_interface;

@@ -78,9 +75,7 @@ struct usb_handle {
static const GUID usb_class_id = ANDROID_USB_CLASS_ID;

/// List of opened usb handles
static usb_handle handle_list = {
    .prev = &handle_list, .next = &handle_list,
};
static std::vector<usb_handle*> handle_list;

/// Locker for the list of opened usb handles
static std::mutex& usb_lock = *new std::mutex();
@@ -131,11 +126,9 @@ void usb_kick(usb_handle* handle);
int usb_close(usb_handle* handle);

int known_device_locked(const wchar_t* dev_name) {
    usb_handle* usb;

    if (NULL != dev_name) {
        // Iterate through the list looking for the name match.
        for (usb = handle_list.next; usb != &handle_list; usb = usb->next) {
        for (usb_handle* usb : handle_list) {
            // In Windows names are not case sensetive!
            if ((NULL != usb->interface_name) && (0 == wcsicmp(usb->interface_name, dev_name))) {
                return 1;
@@ -168,10 +161,7 @@ int register_new_device(usb_handle* handle) {
    }

    // Not in the list. Add this handle to the list.
    handle->next = &handle_list;
    handle->prev = handle_list.prev;
    handle->prev->next = handle;
    handle->next->prev = handle;
    handle_list.push_back(handle);

    return 1;
}
@@ -274,10 +264,6 @@ usb_handle* do_usb_open(const wchar_t* interface_name) {
        goto fail;
    }

    // Set linkers back to the handle
    ret->next = ret;
    ret->prev = ret;

    // Create interface.
    ret->adb_interface = AdbCreateInterfaceByName(interface_name);
    if (NULL == ret->adb_interface) {
@@ -484,13 +470,8 @@ int usb_close(usb_handle* handle) {
        // Remove handle from the list
        {
            std::lock_guard<std::mutex> lock(usb_lock);

            if ((handle->next != handle) && (handle->prev != handle)) {
                handle->next->prev = handle->prev;
                handle->prev->next = handle->next;
                handle->prev = handle;
                handle->next = handle;
            }
            handle_list.erase(std::remove(handle_list.begin(), handle_list.end(), handle),
                              handle_list.end());
        }

        // Cleanup handle
@@ -623,7 +604,9 @@ static void kick_devices() {
    // Need to acquire lock to safely walk the list which might be modified
    // by another thread.
    std::lock_guard<std::mutex> lock(usb_lock);
    for (usb_handle* usb = handle_list.next; usb != &handle_list; usb = usb->next) {
    for (usb_handle* usb : handle_list) {
        usb_kick_locked(usb);
    }
}

}  // namespace native
+1 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ int is_adb_interface(int usb_class, int usb_subclass, int usb_protocol)
}

bool should_use_libusb() {
#if defined(_WIN32) || !ADB_HOST
#if !ADB_HOST
    return false;
#else
    static bool enable = getenv("ADB_LIBUSB") && strcmp(getenv("ADB_LIBUSB"), "1") == 0;
+2 −2
Original line number Diff line number Diff line
@@ -29,8 +29,8 @@
    void usb_kick(handle_ref_type h);                            \
    size_t usb_get_max_packet_size(handle_ref_type)

#if defined(_WIN32) || !ADB_HOST
// Windows and the daemon have a single implementation.
#if !ADB_HOST
// The daemon has a single implementation.

struct usb_handle;
ADB_USB_INTERFACE(usb_handle*);