Report USB device disconnection when detected
USB device disconnection is detected via a hotplug callback when it is supported. In addition, report disconnection on libusb calls returning LIBUSB_ERROR_NO_DEVICE or LIBUSB_ERROR_NOT_FOUND. This allows to detect disconnection after a libusb call when hotplug is not available. PR #3011 <https://github.com/Genymobile/scrcpy/pull/3011>
This commit is contained in:
parent
3ee3f8dc02
commit
be1936bb85
3 changed files with 30 additions and 2 deletions
|
@ -95,6 +95,7 @@ sc_aoa_register_hid(struct sc_aoa *aoa, uint16_t accessory_id,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOGE("REGISTER_HID: libusb error: %s", libusb_strerror(result));
|
LOGE("REGISTER_HID: libusb error: %s", libusb_strerror(result));
|
||||||
|
sc_usb_check_disconnected(aoa->usb, result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +132,7 @@ sc_aoa_set_hid_report_desc(struct sc_aoa *aoa, uint16_t accessory_id,
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOGE("SET_HID_REPORT_DESC: libusb error: %s", libusb_strerror(result));
|
LOGE("SET_HID_REPORT_DESC: libusb error: %s", libusb_strerror(result));
|
||||||
|
sc_usb_check_disconnected(aoa->usb, result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +175,7 @@ sc_aoa_send_hid_event(struct sc_aoa *aoa, const struct sc_hid_event *event) {
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOGE("SEND_HID_EVENT: libusb error: %s", libusb_strerror(result));
|
LOGE("SEND_HID_EVENT: libusb error: %s", libusb_strerror(result));
|
||||||
|
sc_usb_check_disconnected(aoa->usb, result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,6 +198,7 @@ sc_aoa_unregister_hid(struct sc_aoa *aoa, const uint16_t accessory_id) {
|
||||||
DEFAULT_TIMEOUT);
|
DEFAULT_TIMEOUT);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
LOGE("UNREGISTER_HID: libusb error: %s", libusb_strerror(result));
|
LOGE("UNREGISTER_HID: libusb error: %s", libusb_strerror(result));
|
||||||
|
sc_usb_check_disconnected(aoa->usb, result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,24 @@ sc_usb_destroy(struct sc_usb *usb) {
|
||||||
libusb_exit(usb->context);
|
libusb_exit(usb->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sc_usb_report_disconnected(struct sc_usb *usb) {
|
||||||
|
if (usb->cbs && !atomic_flag_test_and_set(&usb->disconnection_notified)) {
|
||||||
|
assert(usb->cbs && usb->cbs->on_disconnected);
|
||||||
|
usb->cbs->on_disconnected(usb, usb->cbs_userdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sc_usb_check_disconnected(struct sc_usb *usb, int result) {
|
||||||
|
if (result == LIBUSB_ERROR_NO_DEVICE || result == LIBUSB_ERROR_NOT_FOUND) {
|
||||||
|
sc_usb_report_disconnected(usb);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device,
|
sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device,
|
||||||
libusb_hotplug_event event, void *userdata) {
|
libusb_hotplug_event event, void *userdata) {
|
||||||
|
@ -232,8 +250,7 @@ sc_usb_libusb_callback(libusb_context *ctx, libusb_device *device,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(usb->cbs && usb->cbs->on_disconnected);
|
sc_usb_report_disconnected(usb);
|
||||||
usb->cbs->on_disconnected(usb, usb->cbs_userdata);
|
|
||||||
|
|
||||||
// Do not automatically deregister the callback by returning 1. Instead,
|
// Do not automatically deregister the callback by returning 1. Instead,
|
||||||
// manually deregister to interrupt libusb_handle_events() from the libusb
|
// manually deregister to interrupt libusb_handle_events() from the libusb
|
||||||
|
@ -307,6 +324,7 @@ sc_usb_connect(struct sc_usb *usb, libusb_device *device,
|
||||||
|
|
||||||
if (cbs) {
|
if (cbs) {
|
||||||
atomic_init(&usb->stopped, false);
|
atomic_init(&usb->stopped, false);
|
||||||
|
usb->disconnection_notified = (atomic_flag) ATOMIC_FLAG_INIT;
|
||||||
if (sc_usb_register_callback(usb)) {
|
if (sc_usb_register_callback(usb)) {
|
||||||
// Create a thread to process libusb events, so that device
|
// Create a thread to process libusb events, so that device
|
||||||
// disconnection could be detected immediately
|
// disconnection could be detected immediately
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct sc_usb {
|
||||||
sc_thread libusb_event_thread;
|
sc_thread libusb_event_thread;
|
||||||
|
|
||||||
atomic_bool stopped; // only used if cbs != NULL
|
atomic_bool stopped; // only used if cbs != NULL
|
||||||
|
atomic_flag disconnection_notified;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sc_usb_callbacks {
|
struct sc_usb_callbacks {
|
||||||
|
@ -73,6 +74,11 @@ sc_usb_connect(struct sc_usb *usb, libusb_device *device,
|
||||||
void
|
void
|
||||||
sc_usb_disconnect(struct sc_usb *usb);
|
sc_usb_disconnect(struct sc_usb *usb);
|
||||||
|
|
||||||
|
// A client should call this function with the return value of a libusb call
|
||||||
|
// to detect disconnection immediately
|
||||||
|
bool
|
||||||
|
sc_usb_check_disconnected(struct sc_usb *usb, int result);
|
||||||
|
|
||||||
void
|
void
|
||||||
sc_usb_stop(struct sc_usb *usb);
|
sc_usb_stop(struct sc_usb *usb);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue