mirror of https://github.com/nirenjan/libx52.git
Use libusb hotplug API to automatically detect disconnection
Prior to this commit, the libx52_is_connected API was simply checking if the device handle was non-NULL. However, this was insufficient, since the device disconnection would not reset the handle, and was relying on the daemon to manually disconnect. The libusb hotplug API provides functionality to register a callback on device insertion/removal. libx52 only registers for removal, and will automatically disconnect the device on receiving the callback. This also modifies libx52_is_connected to fallback to checking if the kernel driver is active if the linked libusb does not support hotplug (unlikely). Finally, this commit adds support for the new hotplug related functions to the libusbx52 preload library. While the preload library doesn't actually support hotplug, it is sufficient to pretend that it does.reverse-scroll
parent
f2884c57b7
commit
627c1fb004
|
@ -277,3 +277,25 @@ int libusb_control_transfer(libusb_device_handle *dev_handle,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int libusb_kernel_driver_active(libusb_device_handle *hdl, int interface_number)
|
||||||
|
{
|
||||||
|
return (hdl->dev->ref_count > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicate that the stub library can support hotplug, even though it doesn't */
|
||||||
|
int libusb_has_capability(uint32_t capability)
|
||||||
|
{
|
||||||
|
return capability == LIBUSB_CAP_HAS_HOTPLUG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dummy function to simulate registering callbacks */
|
||||||
|
int libusb_hotplug_register_callback(libusb_context *ctx,
|
||||||
|
libusb_hotplug_event events,
|
||||||
|
libusb_hotplug_flag flags,
|
||||||
|
int vendor_id, int product_id, int dev_class,
|
||||||
|
libusb_hotplug_callback_fn cb_fn, void *user_data,
|
||||||
|
libusb_hotplug_callback_handle *callback_handle)
|
||||||
|
{
|
||||||
|
return LIBUSB_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ lib_LTLIBRARIES += libx52.la
|
||||||
# See: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# See: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
libx52_v_CUR=6
|
libx52_v_CUR=6
|
||||||
libx52_v_AGE=4
|
libx52_v_AGE=4
|
||||||
libx52_v_REV=0
|
libx52_v_REV=1
|
||||||
libx52_la_SOURCES = \
|
libx52_la_SOURCES = \
|
||||||
libx52/x52_control.c \
|
libx52/x52_control.c \
|
||||||
libx52/x52_core.c \
|
libx52/x52_core.c \
|
||||||
|
|
|
@ -51,6 +51,9 @@ struct libx52_device {
|
||||||
|
|
||||||
int timezone[X52_MFD_CLOCKS];
|
int timezone[X52_MFD_CLOCKS];
|
||||||
libx52_clock_format time_format[X52_MFD_CLOCKS];
|
libx52_clock_format time_format[X52_MFD_CLOCKS];
|
||||||
|
|
||||||
|
libusb_hotplug_callback_handle hotplug_handle;
|
||||||
|
int handle_registered;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Flag bits */
|
/** Flag bits */
|
||||||
|
|
|
@ -42,9 +42,52 @@ static int libx52_device_is_x52pro(uint16_t idProduct)
|
||||||
return (idProduct == X52_PROD_X52PRO);
|
return (idProduct == X52_PROD_X52PRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _x52_hotplug_callback(libusb_context *ctx,
|
||||||
|
libusb_device *device,
|
||||||
|
libusb_hotplug_event event, void *user_data)
|
||||||
|
{
|
||||||
|
libx52_device *dev = user_data;
|
||||||
|
|
||||||
|
if (dev == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Double check that the context matches the libx52 structure */
|
||||||
|
if (dev->ctx != ctx) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) {
|
||||||
|
/*
|
||||||
|
* Return 1 if we successfully disconnected. This will automatically
|
||||||
|
* deregister the callback.
|
||||||
|
*/
|
||||||
|
return (libx52_disconnect(dev) == LIBX52_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool libx52_is_connected(libx52_device *dev)
|
bool libx52_is_connected(libx52_device *dev)
|
||||||
{
|
{
|
||||||
return (dev && dev->hdl);
|
int rc;
|
||||||
|
|
||||||
|
if (!dev) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (dev->hdl) {
|
||||||
|
if (dev->handle_registered) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if interface 0 has a kernel driver attached */
|
||||||
|
rc = libusb_kernel_driver_active(dev->hdl, 0);
|
||||||
|
return (rc == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int libx52_disconnect(libx52_device *dev)
|
int libx52_disconnect(libx52_device *dev)
|
||||||
|
@ -57,6 +100,7 @@ int libx52_disconnect(libx52_device *dev)
|
||||||
libusb_close(dev->hdl);
|
libusb_close(dev->hdl);
|
||||||
dev->hdl = NULL;
|
dev->hdl = NULL;
|
||||||
dev->flags = 0;
|
dev->flags = 0;
|
||||||
|
dev->handle_registered = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LIBX52_SUCCESS;
|
return LIBX52_SUCCESS;
|
||||||
|
@ -112,6 +156,23 @@ int libx52_connect(libx52_device *dev)
|
||||||
return LIBX52_ERROR_NO_DEVICE;
|
return LIBX52_ERROR_NO_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Setup hotplug callback when this device is disconnected */
|
||||||
|
if (libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
|
||||||
|
/*
|
||||||
|
* Mark if the hotplug callback registered successfully. If it did
|
||||||
|
* not register, we can use the kernel driver API to determine if
|
||||||
|
* the device is still connected.
|
||||||
|
*/
|
||||||
|
dev->handle_registered = (LIBUSB_SUCCESS ==
|
||||||
|
libusb_hotplug_register_callback(dev->ctx,
|
||||||
|
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0,
|
||||||
|
desc.idVendor, desc.idProduct,
|
||||||
|
LIBUSB_HOTPLUG_MATCH_ANY,
|
||||||
|
_x52_hotplug_callback, dev,
|
||||||
|
&(dev->hotplug_handle)));
|
||||||
|
}
|
||||||
|
|
||||||
return LIBX52_SUCCESS;
|
return LIBX52_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue