From 4fd8bf9bb85e18c3881d976f943f939aaf168b95 Mon Sep 17 00:00:00 2001 From: Yuki Joou Date: Tue, 11 Jul 2023 21:02:56 +0200 Subject: [PATCH] usb_device_detection: Added support for detecting basestation un/plugs --- build.sh | 4 +- main.c | 22 +++++++++- usb_device_detection.c | 99 ++++++++++++++++++++++++++++++++++++++++++ usb_device_detection.h | 20 +++++++++ 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 usb_device_detection.c create mode 100644 usb_device_detection.h diff --git a/build.sh b/build.sh index 9eda679..892c093 100755 --- a/build.sh +++ b/build.sh @@ -2,9 +2,9 @@ set -ex; -SOURCES="main.c output_manager.c accel_monitor.c" +SOURCES="main.c output_manager.c accel_monitor.c usb_device_detection.c" CFLAGS="-std=c2x -Wall -Wextra -pedantic $CFLAGS" -LIBS="-lwayland-client protocol/wlr-output-management-unstable-v1.c" +LIBS="-lwayland-client -lusb-1.0 protocol/wlr-output-management-unstable-v1.c" OUTPUT=miix-wlr clang $CFLAGS $LIBS $SOURCES -o $OUTPUT diff --git a/main.c b/main.c index 96f7218..9509da6 100644 --- a/main.c +++ b/main.c @@ -1,9 +1,11 @@ #include #include -#include "output_manager.h" +#include #include "accel_monitor.h" +#include "output_manager.h" +#include "usb_device_detection.h" static enum wl_output_transform const SENSOR_TO_OUTPUT_ROTATION[] = { [ACCEL_ROTATION_0DEG] = WL_OUTPUT_TRANSFORM_270, @@ -16,6 +18,9 @@ static char const* const DEFAULT_OUTPUT = "DSI-1"; static char const* const DEFAULT_MOTION_SENSOR = "/sys/bus/iio/devices/iio:device0"; +static uint16_t const BASESTATION_VENDOR_ID = 0x048d; +static uint16_t const BASESTATION_PRODUCT_ID = 0x8911; + static enum accel_rotation last_accel_rotation = ACCEL_ROTATION_NO_CHANGE; int main(int, char**) @@ -27,11 +32,25 @@ int main(int, char**) return -1; } + struct usb_detector* base_station_detector = + create_detector(BASESTATION_VENDOR_ID, BASESTATION_PRODUCT_ID); + struct miix_wlr_state* state = miix_wlr_init(); for (;;) { if (!monitor->data_is_ready) continue; + if (base_station_detector && base_station_detector->is_connected) { + if (last_accel_rotation != ACCEL_ROTATION_0DEG) { + miix_wlr_head_set_transform( + state, + DEFAULT_OUTPUT, + SENSOR_TO_OUTPUT_ROTATION[ACCEL_ROTATION_0DEG]); + last_accel_rotation = ACCEL_ROTATION_0DEG; + } + continue; + } + enum accel_rotation rotation = accel_get_current_rotation(monitor); if (rotation == ACCEL_ROTATION_NO_CHANGE || rotation == last_accel_rotation) @@ -42,5 +61,6 @@ int main(int, char**) } accel_stop_monitor(monitor); + destroy_detector(base_station_detector); miix_wlr_cleanup(state); } diff --git a/usb_device_detection.c b/usb_device_detection.c new file mode 100644 index 0000000..762d622 --- /dev/null +++ b/usb_device_detection.c @@ -0,0 +1,99 @@ +#include "usb_device_detection.h" + +#include +#include + +int hotplug_callback(struct libusb_context*, + struct libusb_device*, + libusb_hotplug_event event, + void* user_data) +{ + struct usb_detector* detector = user_data; + + if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) + detector->is_connected = true; + else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) + detector->is_connected = false; + else + printf("Unexpected USB device event %d\n", event); + + return 0; +} + +static int libusb_event_handler(void* data) +{ + struct usb_detector* detector = data; + + while (!detector->event_handler_should_exit) { + thrd_sleep(&(struct timespec){.tv_sec = 1}, NULL); + libusb_handle_events(detector->usb_context); + } + + return 0; +} + +struct usb_detector* create_detector(uint16_t vendor_id, uint16_t product_id) +{ + + struct libusb_context* usb_context; + libusb_init(&usb_context); + + if (!usb_context) { + fprintf(stderr, + "Couldn't get USB contexxt. Device detection will not work\n"); + return 0; + } + + struct usb_detector* detector = calloc(1, sizeof(struct usb_detector)); + detector->usb_context = usb_context; + + if (libusb_hotplug_register_callback(detector->usb_context, + LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | + LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, + LIBUSB_HOTPLUG_ENUMERATE, + vendor_id, + product_id, + LIBUSB_HOTPLUG_MATCH_ANY, + hotplug_callback, + detector, + &detector->hotplug_handle) != + LIBUSB_SUCCESS) { + + fprintf(stderr, + "Couldn't register usb hotplug listener. Device detection " + "will not work.\n"); + free(detector); + return 0; + } + + detector->is_connected = false; + detector->event_handler_should_exit = false; + + if (thrd_create(&detector->event_handler_thread, + &libusb_event_handler, + detector) != thrd_success) { + fprintf(stderr, + "Couldn't start event handler. Device detection will not " + "work.\n"); + free(detector); + return 0; + } + + return detector; +} + +void destroy_detector(struct usb_detector* detector) +{ + libusb_hotplug_deregister_callback(detector->usb_context, + detector->hotplug_handle); + + detector->event_handler_should_exit = true; + if (thrd_join(detector->event_handler_thread, 0) != thrd_success) + fprintf(stderr, + "Couldn't join with usb event handler thread, something went " + "really wrong, we likely won't exit cleanly\n"); + + libusb_exit(detector->usb_context); + + free(detector); +} diff --git a/usb_device_detection.h b/usb_device_detection.h new file mode 100644 index 0000000..8af8e4f --- /dev/null +++ b/usb_device_detection.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +#include + +struct usb_detector { + atomic_bool is_connected; + + atomic_bool event_handler_should_exit; + thrd_t event_handler_thread; + + struct libusb_context* usb_context; + libusb_hotplug_callback_handle hotplug_handle; +}; + +struct usb_detector* create_detector(uint16_t vendor_id, uint16_t product_id); +void destroy_detector(struct usb_detector*);