#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; if (detector->has_hotplug_callbacks) detector->on_connected(); } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) { detector->is_connected = false; if (detector->has_hotplug_callbacks) detector->on_disconnected(); } 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_completed(detector->usb_context, NULL); } 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; detector->is_connected = false; detector->event_handler_should_exit = false; detector->has_hotplug_callbacks = false; 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; } 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); }