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;
}
int handle_device_lusb(libusb_device *d) {
libusb_device_handle *h;
int status = libusb_open(d, &h);
if (status < 0 || h == NULL) {
printf("Error opening device, %i.\n", status);
return 0;
// GLOBAL: for main and hotplug_callback
static int HOT_COUNT = 0;
static struct libusb_transfer *TX = NULL;
void loop() {
int status = 0;
int LAST_HOT_COUNT = 0;
while (1) {
if (TX != NULL && TX->dev_handle != 0) {
status = libusb_submit_transfer(TX);
}
if (status < 0 && LAST_HOT_COUNT != HOT_COUNT) {
printf("\nwarning: usb transfer status = %i\n", status);
//continue;
}
LAST_HOT_COUNT = HOT_COUNT;
libusb_handle_events_completed(NULL, NULL);
}
struct libevdev *evdev = NULL;
struct libevdev_uinput *uidev = NULL;
printf("handle_device: %x\n", uidev);
if (init_ctrl(d, &evdev, &uidev) < 0) {
return 0;
}
if (evdev == NULL || uidev == NULL) {
printf("Error initializing controls, %x, %x.\n", evdev, uidev);
return 0;
}
struct libusb_transfer *tx;
const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v
//AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v
unsigned char buffer[AM_PACKET_LEN];
}
// Allocate memory for transfer, configure, then submit
tx = libusb_alloc_transfer(0);
libusb_fill_interrupt_transfer(
tx,
h,
// 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);
}
const int ENDPOINT_ADDR = 0x81; // bEndpointAddress from lsusb -v
//AM_PACKET_LEN = 10; // wMaxPacketSize from lsusb -v
unsigned char buffer[AM_PACKET_LEN];
TX = libusb_alloc_transfer(0);
libusb_fill_interrupt_transfer(
TX,
dev_handle,
ENDPOINT_ADDR,
buffer,
AM_PACKET_LEN,
callback_default,
uidev, // extra data to send in tx
130); // timeout in milliseconds
do {
status = libusb_submit_transfer(tx);
if (status < 0 ) {
printf("warning: usb transfer status = %i\n", status);
//continue;
130 // timeout in milliseconds
);
}
} else if (LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
if (dev_handle) {
libusb_close(dev_handle);
dev_handle = NULL;
libevdev_uinput_destroy(uidev);
libusb_free_transfer(TX);
TX = NULL;
}
} else {
printf ("INFO: Device left, but handle did not exist.\n");
}
libusb_handle_events(NULL);
} while (1);
libevdev_uinput_destroy(uidev);
HOT_COUNT++;
return 0;
}
@ -496,25 +526,29 @@ int main() {
#define UNREF_DEVICE 1
#define KEEP_DEVICE_REF 0
libusb_device ** devs;
int r = libusb_init(NULL);
if (r < 0) {
return r;
}
int count = libusb_get_device_list(NULL, &devs);
if (count < 0) {
libusb_hotplug_callback_handle callback_handle;
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);
return count;
return EXIT_FAILURE;
}
int index = find_device(devs, count);
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);
loop();
return 0;
}