scuti/hotplug (#11)

Added hotplugging support.
This commit is contained in:
scuti 2021-09-28 20:34:21 -07:00 committed by Gitea
parent 894c82c381
commit ee3b7b2182

View File

@ -447,48 +447,78 @@ int init_ctrl(struct libusb_device * const d,
return is_ok; return is_ok;
} }
int handle_device_lusb(libusb_device *d) { // GLOBAL: for main and hotplug_callback
libusb_device_handle *h; static int HOT_COUNT = 0;
int status = libusb_open(d, &h); static struct libusb_transfer *TX = NULL;
if (status < 0 || h == NULL) { void loop() {
printf("Error opening device, %i.\n", status); int status = 0;
return 0; int LAST_HOT_COUNT = 0;
while (1) {
if (TX != NULL && TX->dev_handle != 0) {
status = libusb_submit_transfer(TX);
} }
struct libevdev *evdev = NULL; if (status < 0 && LAST_HOT_COUNT != HOT_COUNT) {
struct libevdev_uinput *uidev = NULL; printf("\nwarning: usb transfer status = %i\n", status);
printf("handle_device: %x\n", uidev); //continue;
if (init_ctrl(d, &evdev, &uidev) < 0) {
return 0;
} }
if (evdev == NULL || uidev == NULL) { LAST_HOT_COUNT = HOT_COUNT;
printf("Error initializing controls, %x, %x.\n", evdev, uidev); libusb_handle_events_completed(NULL, NULL);
return 0; }
}
// TODO: make scuti explain why this is called twice
int hotplug_callback(struct libusb_context *ctx, struct libusb_device *dev,
libusb_hotplug_event event, void *user_data) {
static libusb_device_handle *dev_handle;
static struct libevdev_uinput *uidev = NULL;
static struct libevdev *evdev = NULL;
struct libusb_device_descriptor desc;
int rc;
libusb_get_device_descriptor(dev, &desc);
if (LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED == event) {
// check if the device supported
libusb_device *devs[1] = {dev};
int index = find_device(devs, 1);
if (index < 0) {
printf("INFO: Detected Hanvon device, but it is not supported.\n");
} else {
// libusb functions that accept libusb_device = SAFE
// submit asynchronous transfers = SAFE
// other functions that accept device handle = NOT SAFE
libusb_open(dev, &dev_handle);
if (init_ctrl(dev, &evdev, &uidev) < 0) {
printf("Error: Could not initialize controls.\n");
exit(EXIT_FAILURE);
} }
struct libusb_transfer *tx;
const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v
//AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v //AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v
unsigned char buffer[AM_PACKET_LEN]; unsigned char buffer[AM_PACKET_LEN];
TX = libusb_alloc_transfer(0);
// Allocate memory for transfer, configure, then submit
tx = libusb_alloc_transfer(0);
libusb_fill_interrupt_transfer( libusb_fill_interrupt_transfer(
tx, TX,
h, dev_handle,
ENDPOINT_ADDR, ENDPOINT_ADDR,
buffer, buffer,
AM_PACKET_LEN, AM_PACKET_LEN,
callback_default, callback_default,
uidev, // extra data to send in tx uidev, // extra data to send in tx
130); // timeout in milliseconds 130 // timeout in milliseconds
do { );
status = libusb_submit_transfer(tx);
if (status < 0 ) {
printf("warning: usb transfer status = %i\n", status);
//continue;
} }
libusb_handle_events(NULL); } else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
} while (1); if (dev_handle) {
libusb_close(dev_handle);
dev_handle = NULL;
libevdev_uinput_destroy(uidev); libevdev_uinput_destroy(uidev);
libusb_free_transfer(TX);
TX = NULL;
}
} else {
printf ("INFO: Device left, but handle did not exist.\n");
}
HOT_COUNT++;
return 0; return 0;
} }
@ -496,25 +526,29 @@ int main() {
#define UNREF_DEVICE 1 #define UNREF_DEVICE 1
#define KEEP_DEVICE_REF 0 #define KEEP_DEVICE_REF 0
libusb_device ** devs;
int r = libusb_init(NULL); int r = libusb_init(NULL);
if (r < 0) { if (r < 0) {
return r; return r;
} }
int count = libusb_get_device_list(NULL, &devs); libusb_hotplug_callback_handle callback_handle;
if (count < 0) { int rc;
rc = libusb_hotplug_register_callback(
NULL,
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
0,
VENDOR_ID_HANVON, // VENDOR
LIBUSB_HOTPLUG_MATCH_ANY, // PRODUCT
LIBUSB_HOTPLUG_MATCH_ANY, // DEV CLASS
hotplug_callback,
NULL,
&callback_handle
);
if (rc != LIBUSB_SUCCESS) {
printf("Error creating a hotplug callback\n");
libusb_exit(NULL); libusb_exit(NULL);
return count; return EXIT_FAILURE;
} }
int index = find_device(devs, count); loop();
if (index < 0) {
printf("Device not plugged in\n");
libusb_exit(NULL);
return 0;
}
libusb_device *device = devs[index];
libusb_free_device_list (devs, UNREF_DEVICE);
int s = handle_device_lusb(device);
libusb_exit(NULL);
return 0; return 0;
} }