Merge "adb: get libusb compiling on Windows."
This commit is contained in:
commit
6f29887c71
5 changed files with 75 additions and 97 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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…
Add table
Reference in a new issue