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
This commit is contained in:
parent
cce381e307
commit
9425996b45
|
@ -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
|
||||
|
|
|
@ -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,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_info*>(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<std::mutex> 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<std::mutex> device_lock) {
|
||||
libusb_transfer* transfer = info->transfer;
|
||||
|
||||
transfer->user_data = info;
|
||||
transfer->callback = [](libusb_transfer* transfer) {
|
||||
transfer_info* info = static_cast<transfer_info*>(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<std::mutex> 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<std::mutex> lock(info->mutex);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*);
|
||||
|
|
Loading…
Reference in New Issue