From 9425996b4521eae0571b4af30056c44bb0482598 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 8 Dec 2017 13:05:40 -0800 Subject: [PATCH] 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 --- adb/Android.mk | 14 ++--- adb/client/usb_libusb.cpp | 111 ++++++++++++++++++------------------- adb/client/usb_windows.cpp | 41 ++++---------- adb/transport_usb.cpp | 2 +- adb/usb.h | 4 +- 5 files changed, 75 insertions(+), 97 deletions(-) diff --git a/adb/Android.mk b/adb/Android.mk index 2b6df7060..d76d17534 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -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 diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp index 81201995a..a5e6f2334 100644 --- a/adb/client/usb_libusb.cpp +++ b/adb/client/usb_libusb.cpp @@ -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 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(device_address, device_serial, std::move(handle), - interface_num, bulk_in, bulk_out, zero_mask, packet_size); + std::unique_ptr 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,59 +491,60 @@ void usb_cleanup() { libusb_hotplug_deregister_callback(nullptr, hotplug_handle); } +static LIBUSB_CALL void transfer_callback(libusb_transfer* transfer) { + transfer_info* info = static_cast(transfer->user_data); + + LOG(DEBUG) << info->name << " transfer callback entered"; + + // Make sure that the original submitter has made it to the condition_variable wait. + std::unique_lock lock(info->mutex); + + 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); + info->Notify(); + return; + } + + // usb_read() can return when receiving some data. + if (info->is_bulk_out && transfer->actual_length != transfer->length) { + LOG(DEBUG) << info->name << " transfer incomplete, resubmitting"; + transfer->length -= transfer->actual_length; + transfer->buffer += transfer->actual_length; + int rc = libusb_submit_transfer(transfer); + if (rc != 0) { + LOG(WARNING) << "failed to submit " << info->name + << " transfer: " << libusb_error_name(rc); + transfer->status = LIBUSB_TRANSFER_ERROR; + info->Notify(); + } + return; + } + + if (should_perform_zero_transfer(transfer->endpoint, transfer->length, info->zero_mask)) { + LOG(DEBUG) << "submitting zero-length write"; + transfer->length = 0; + int rc = libusb_submit_transfer(transfer); + if (rc != 0) { + LOG(WARNING) << "failed to submit zero-length write: " << libusb_error_name(rc); + transfer->status = LIBUSB_TRANSFER_ERROR; + info->Notify(); + } + return; + } + + 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 device_lock) { libusb_transfer* transfer = info->transfer; transfer->user_data = info; - transfer->callback = [](libusb_transfer* transfer) { - transfer_info* info = static_cast(transfer->user_data); - - LOG(DEBUG) << info->name << " transfer callback entered"; - - // Make sure that the original submitter has made it to the condition_variable wait. - std::unique_lock lock(info->mutex); - - 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); - info->Notify(); - return; - } - - // usb_read() can return when receiving some data. - if (info->is_bulk_out && transfer->actual_length != transfer->length) { - LOG(DEBUG) << info->name << " transfer incomplete, resubmitting"; - transfer->length -= transfer->actual_length; - transfer->buffer += transfer->actual_length; - int rc = libusb_submit_transfer(transfer); - if (rc != 0) { - LOG(WARNING) << "failed to submit " << info->name - << " transfer: " << libusb_error_name(rc); - transfer->status = LIBUSB_TRANSFER_ERROR; - info->Notify(); - } - return; - } - - if (should_perform_zero_transfer(transfer->endpoint, transfer->length, info->zero_mask)) { - LOG(DEBUG) << "submitting zero-length write"; - transfer->length = 0; - int rc = libusb_submit_transfer(transfer); - if (rc != 0) { - LOG(WARNING) << "failed to submit zero-length write: " << libusb_error_name(rc); - transfer->status = LIBUSB_TRANSFER_ERROR; - info->Notify(); - } - return; - } - - LOG(VERBOSE) << info->name << "transfer fully complete"; - info->Notify(); - }; + transfer->callback = transfer_callback; LOG(DEBUG) << "locking " << info->name << " transfer_info mutex"; std::unique_lock lock(info->mutex); diff --git a/adb/client/usb_windows.cpp b/adb/client/usb_windows.cpp index 61981b179..9751ebf79 100644 --- a/adb/client/usb_windows.cpp +++ b/adb/client/usb_windows.cpp @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -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 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 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 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 diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp index fdecccfc3..895f922be 100644 --- a/adb/transport_usb.cpp +++ b/adb/transport_usb.cpp @@ -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; diff --git a/adb/usb.h b/adb/usb.h index f428ede48..cd83c42ae 100644 --- a/adb/usb.h +++ b/adb/usb.h @@ -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*);