Extract USB handling from AOA
The AOA code handled both USB initialization and AOA commands/events. Extract USB-related code to a separate file and structure. PR #2974 <https://github.com/Genymobile/scrcpy/pull/2974>
This commit is contained in:
parent
d48d191262
commit
1d6f9952ee
5 changed files with 143 additions and 95 deletions
|
@ -78,6 +78,7 @@ if usb_support
|
||||||
'src/usb/aoa_hid.c',
|
'src/usb/aoa_hid.c',
|
||||||
'src/usb/hid_keyboard.c',
|
'src/usb/hid_keyboard.c',
|
||||||
'src/usb/hid_mouse.c',
|
'src/usb/hid_mouse.c',
|
||||||
|
'src/usb/usb.c',
|
||||||
]
|
]
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -50,74 +50,6 @@ log_libusb_error(enum libusb_error errcode) {
|
||||||
LOGW("libusb error: %s", libusb_strerror(errcode));
|
LOGW("libusb error: %s", libusb_strerror(errcode));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
accept_device(libusb_device *device, const char *serial) {
|
|
||||||
// do not log any USB error in this function, it is expected that many USB
|
|
||||||
// devices available on the computer have permission restrictions
|
|
||||||
|
|
||||||
struct libusb_device_descriptor desc;
|
|
||||||
int result = libusb_get_device_descriptor(device, &desc);
|
|
||||||
if (result < 0 || !desc.iSerialNumber) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_device_handle *handle;
|
|
||||||
result = libusb_open(device, &handle);
|
|
||||||
if (result < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buffer[128];
|
|
||||||
result = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
|
|
||||||
(unsigned char *) buffer,
|
|
||||||
sizeof(buffer));
|
|
||||||
libusb_close(handle);
|
|
||||||
if (result < 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[sizeof(buffer) - 1] = '\0'; // just in case
|
|
||||||
|
|
||||||
// accept the device if its serial matches
|
|
||||||
return !strcmp(buffer, serial);
|
|
||||||
}
|
|
||||||
|
|
||||||
static libusb_device *
|
|
||||||
sc_aoa_find_usb_device(const char *serial) {
|
|
||||||
if (!serial) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
libusb_device **list;
|
|
||||||
libusb_device *result = NULL;
|
|
||||||
ssize_t count = libusb_get_device_list(NULL, &list);
|
|
||||||
if (count < 0) {
|
|
||||||
log_libusb_error((enum libusb_error) count);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (size_t) count; ++i) {
|
|
||||||
libusb_device *device = list[i];
|
|
||||||
|
|
||||||
if (accept_device(device, serial)) {
|
|
||||||
result = libusb_ref_device(device);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
libusb_free_device_list(list, 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
sc_aoa_open_usb_handle(libusb_device *device, libusb_device_handle **handle) {
|
|
||||||
int result = libusb_open(device, handle);
|
|
||||||
if (result < 0) {
|
|
||||||
log_libusb_error((enum libusb_error) result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sc_aoa_init(struct sc_aoa *aoa, const char *serial,
|
sc_aoa_init(struct sc_aoa *aoa, const char *serial,
|
||||||
struct sc_acksync *acksync) {
|
struct sc_acksync *acksync) {
|
||||||
|
@ -133,31 +65,16 @@ sc_aoa_init(struct sc_aoa *aoa, const char *serial,
|
||||||
goto error_destroy_mutex;
|
goto error_destroy_mutex;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libusb_init(&aoa->usb_context) != LIBUSB_SUCCESS) {
|
bool ok = sc_usb_init(&aoa->usb, serial);
|
||||||
|
if (!ok) {
|
||||||
goto error_destroy_cond;
|
goto error_destroy_cond;
|
||||||
}
|
}
|
||||||
|
|
||||||
aoa->usb_device = sc_aoa_find_usb_device(serial);
|
|
||||||
if (!aoa->usb_device) {
|
|
||||||
LOGW("USB device of serial %s not found", serial);
|
|
||||||
goto error_exit_libusb;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sc_aoa_open_usb_handle(aoa->usb_device, &aoa->usb_handle) < 0) {
|
|
||||||
LOGW("Open USB handle failed");
|
|
||||||
goto error_unref_device;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aoa->stopped = false;
|
aoa->stopped = false;
|
||||||
aoa->acksync = acksync;
|
aoa->acksync = acksync;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error_unref_device:
|
|
||||||
libusb_unref_device(aoa->usb_device);
|
|
||||||
error_exit_libusb:
|
|
||||||
libusb_exit(aoa->usb_context);
|
|
||||||
error_destroy_cond:
|
error_destroy_cond:
|
||||||
sc_cond_destroy(&aoa->event_cond);
|
sc_cond_destroy(&aoa->event_cond);
|
||||||
error_destroy_mutex:
|
error_destroy_mutex:
|
||||||
|
@ -173,9 +90,7 @@ sc_aoa_destroy(struct sc_aoa *aoa) {
|
||||||
sc_hid_event_destroy(&event);
|
sc_hid_event_destroy(&event);
|
||||||
}
|
}
|
||||||
|
|
||||||
libusb_close(aoa->usb_handle);
|
sc_usb_destroy(&aoa->usb);
|
||||||
libusb_unref_device(aoa->usb_device);
|
|
||||||
libusb_exit(aoa->usb_context);
|
|
||||||
sc_cond_destroy(&aoa->event_cond);
|
sc_cond_destroy(&aoa->event_cond);
|
||||||
sc_mutex_destroy(&aoa->mutex);
|
sc_mutex_destroy(&aoa->mutex);
|
||||||
}
|
}
|
||||||
|
@ -192,7 +107,7 @@ sc_aoa_register_hid(struct sc_aoa *aoa, uint16_t accessory_id,
|
||||||
uint16_t index = report_desc_size;
|
uint16_t index = report_desc_size;
|
||||||
unsigned char *buffer = NULL;
|
unsigned char *buffer = NULL;
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
int result = libusb_control_transfer(aoa->usb_handle, request_type, request,
|
int result = libusb_control_transfer(aoa->usb.handle, request_type, request,
|
||||||
value, index, buffer, length,
|
value, index, buffer, length,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -228,7 +143,7 @@ sc_aoa_set_hid_report_desc(struct sc_aoa *aoa, uint16_t accessory_id,
|
||||||
// libusb_control_transfer expects a pointer to non-const
|
// libusb_control_transfer expects a pointer to non-const
|
||||||
unsigned char *buffer = (unsigned char *) report_desc;
|
unsigned char *buffer = (unsigned char *) report_desc;
|
||||||
uint16_t length = report_desc_size;
|
uint16_t length = report_desc_size;
|
||||||
int result = libusb_control_transfer(aoa->usb_handle, request_type, request,
|
int result = libusb_control_transfer(aoa->usb.handle, request_type, request,
|
||||||
value, index, buffer, length,
|
value, index, buffer, length,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -270,7 +185,7 @@ sc_aoa_send_hid_event(struct sc_aoa *aoa, const struct sc_hid_event *event) {
|
||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
unsigned char *buffer = event->buffer;
|
unsigned char *buffer = event->buffer;
|
||||||
uint16_t length = event->size;
|
uint16_t length = event->size;
|
||||||
int result = libusb_control_transfer(aoa->usb_handle, request_type, request,
|
int result = libusb_control_transfer(aoa->usb.handle, request_type, request,
|
||||||
value, index, buffer, length,
|
value, index, buffer, length,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -292,7 +207,7 @@ sc_aoa_unregister_hid(struct sc_aoa *aoa, const uint16_t accessory_id) {
|
||||||
uint16_t index = 0;
|
uint16_t index = 0;
|
||||||
unsigned char *buffer = NULL;
|
unsigned char *buffer = NULL;
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
int result = libusb_control_transfer(aoa->usb_handle, request_type, request,
|
int result = libusb_control_transfer(aoa->usb.handle, request_type, request,
|
||||||
value, index, buffer, length,
|
value, index, buffer, length,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <libusb-1.0/libusb.h>
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
#include "util/acksync.h"
|
#include "util/acksync.h"
|
||||||
#include "util/cbuf.h"
|
#include "util/cbuf.h"
|
||||||
#include "util/thread.h"
|
#include "util/thread.h"
|
||||||
|
@ -29,9 +30,7 @@ sc_hid_event_destroy(struct sc_hid_event *hid_event);
|
||||||
struct sc_hid_event_queue CBUF(struct sc_hid_event, 64);
|
struct sc_hid_event_queue CBUF(struct sc_hid_event, 64);
|
||||||
|
|
||||||
struct sc_aoa {
|
struct sc_aoa {
|
||||||
libusb_context *usb_context;
|
struct sc_usb usb;
|
||||||
libusb_device *usb_device;
|
|
||||||
libusb_device_handle *usb_handle;
|
|
||||||
sc_thread thread;
|
sc_thread thread;
|
||||||
sc_mutex mutex;
|
sc_mutex mutex;
|
||||||
sc_cond event_cond;
|
sc_cond event_cond;
|
||||||
|
|
112
app/src/usb/usb.c
Normal file
112
app/src/usb/usb.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#include "usb.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "util/log.h"
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
log_libusb_error(enum libusb_error errcode) {
|
||||||
|
LOGW("libusb error: %s", libusb_strerror(errcode));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
accept_device(libusb_device *device, const char *serial) {
|
||||||
|
// Do not log any USB error in this function, it is expected that many USB
|
||||||
|
// devices available on the computer have permission restrictions
|
||||||
|
|
||||||
|
struct libusb_device_descriptor desc;
|
||||||
|
int result = libusb_get_device_descriptor(device, &desc);
|
||||||
|
if (result < 0 || !desc.iSerialNumber) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
result = libusb_open(device, &handle);
|
||||||
|
if (result < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[128];
|
||||||
|
result = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber,
|
||||||
|
(unsigned char *) buffer,
|
||||||
|
sizeof(buffer));
|
||||||
|
libusb_close(handle);
|
||||||
|
if (result < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[sizeof(buffer) - 1] = '\0'; // just in case
|
||||||
|
|
||||||
|
// Accept the device if its serial matches
|
||||||
|
return !strcmp(buffer, serial);
|
||||||
|
}
|
||||||
|
|
||||||
|
static libusb_device *
|
||||||
|
sc_usb_find_device(const char *serial) {
|
||||||
|
if (!serial) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_device **list;
|
||||||
|
libusb_device *result = NULL;
|
||||||
|
ssize_t count = libusb_get_device_list(NULL, &list);
|
||||||
|
if (count < 0) {
|
||||||
|
log_libusb_error((enum libusb_error) count);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (size_t) count; ++i) {
|
||||||
|
libusb_device *device = list[i];
|
||||||
|
|
||||||
|
if (accept_device(device, serial)) {
|
||||||
|
result = libusb_ref_device(device);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
libusb_free_device_list(list, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static libusb_device_handle *
|
||||||
|
sc_usb_open_handle(libusb_device *device) {
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
int result = libusb_open(device, &handle);
|
||||||
|
if (result < 0) {
|
||||||
|
log_libusb_error((enum libusb_error) result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sc_usb_init(struct sc_usb *usb, const char *serial) {
|
||||||
|
// There is only one device, initialize the context here
|
||||||
|
if (libusb_init(&usb->context) != LIBUSB_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb->device = sc_usb_find_device(serial);
|
||||||
|
if (!usb->device) {
|
||||||
|
LOGW("USB device %s not found", serial);
|
||||||
|
libusb_exit(usb->context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
usb->handle = sc_usb_open_handle(usb->device);
|
||||||
|
if (!usb->handle) {
|
||||||
|
LOGW("Could not open USB device %s", serial);
|
||||||
|
libusb_unref_device(usb->device);
|
||||||
|
libusb_exit(usb->context);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_usb_destroy(struct sc_usb *usb) {
|
||||||
|
libusb_close(usb->handle);
|
||||||
|
libusb_unref_device(usb->device);
|
||||||
|
libusb_exit(usb->context);
|
||||||
|
}
|
21
app/src/usb/usb.h
Normal file
21
app/src/usb/usb.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#ifndef SC_USB_H
|
||||||
|
#define SC_USB_H
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <libusb-1.0/libusb.h>
|
||||||
|
|
||||||
|
struct sc_usb {
|
||||||
|
libusb_context *context;
|
||||||
|
libusb_device *device;
|
||||||
|
libusb_device_handle *handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
sc_usb_init(struct sc_usb *usb, const char *serial);
|
||||||
|
|
||||||
|
void
|
||||||
|
sc_usb_destroy(struct sc_usb *usb);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue