Merge "adb: get libusb compiling on Windows."

This commit is contained in:
Treehugger Robot 2017-12-11 19:24:41 +00:00 committed by Gerrit Code Review
commit 6f29887c71
5 changed files with 75 additions and 97 deletions

View file

@ -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

View file

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

View file

@ -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

View file

@ -195,7 +195,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;

View file

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