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*);