mirror of https://github.com/nirenjan/libx52.git
Add connect/disconnect methods to libx52
Prior to this change, libx52_init needed a supported joystick to be plugged in, otherwise it would fail with LIBX52_ERROR_NO_DEVICE. This change modifies the behavior so that libx52_init would still succeed, but the application should call libx52_connect to make sure that the device handle is valid. libx52_init still tries to connect to the joystick, but absence is no longer treated as a failure. This change also modifies x52cli to check that the joystick is actually connected before calling the individual handlers. Because libx52_init no longer fails if the joystick is absent, we need to rely on the return code from libx52_connect.debian-packaging
parent
93f1091b95
commit
d9ae8d4b79
|
@ -6,11 +6,15 @@ The format is based upon [Keep a Changelog].
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
|
- Connect/Disconnect methods in libx52. These allow for dynamically connecting
|
||||||
|
or disconnecting from a supported joystick without having to reinitialize the
|
||||||
|
library.
|
||||||
- Internationalization for the following:
|
- Internationalization for the following:
|
||||||
* libx52
|
* libx52
|
||||||
* x52test
|
* x52test
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- libx52_init no longer fails when a supported joystick is not connected.
|
||||||
- x52test moves the LED tests to execute after all other tests. See
|
- x52test moves the LED tests to execute after all other tests. See
|
||||||
[#19](https://github.com/nirenjan/x52pro-linux/issues/19).
|
[#19](https://github.com/nirenjan/x52pro-linux/issues/19).
|
||||||
|
|
||||||
|
|
|
@ -227,11 +227,10 @@ typedef enum {
|
||||||
* structures to access the joystick, and returns a \ref libx52_device pointer.
|
* structures to access the joystick, and returns a \ref libx52_device pointer.
|
||||||
* All calls to libx52 use the returned pointer to control the device.
|
* All calls to libx52 use the returned pointer to control the device.
|
||||||
*
|
*
|
||||||
* If no joystick is found `libx52_init()` returns _NULL_.
|
* This function attempts to connect to the joystick upon initialization.
|
||||||
*
|
* However, if no device is connected, then the library initialization does
|
||||||
* @par Limitations
|
* not fail, but the application must call \ref libx52_connect prior to any
|
||||||
* This function does not support hotplugging. The joystick must be plugged in
|
* calls to \ref libx52_update
|
||||||
* before calling this function.
|
|
||||||
*
|
*
|
||||||
* @param[out] dev Pointer to a \ref libx52_device *. This function will
|
* @param[out] dev Pointer to a \ref libx52_device *. This function will
|
||||||
* allocate a device context and return the pointer to that in this variable.
|
* allocate a device context and return the pointer to that in this variable.
|
||||||
|
@ -252,6 +251,33 @@ int libx52_init(libx52_device ** dev);
|
||||||
*/
|
*/
|
||||||
void libx52_exit(libx52_device *dev);
|
void libx52_exit(libx52_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Connect to the X52 device
|
||||||
|
*
|
||||||
|
* Attempt to connect to a supported X52/X52Pro joystick. If no supported
|
||||||
|
* joysticks are found, it will return \ref LIBX52_ERROR_NO_DEVICE. If any
|
||||||
|
* errors are encountered during device enumeration, it will return an
|
||||||
|
* appropriate \ref libx52_error_code.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the device
|
||||||
|
*
|
||||||
|
* @returns \ref libx52_error_code indicating status
|
||||||
|
*/
|
||||||
|
int libx52_connect(libx52_device *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disconnect from the X52 device
|
||||||
|
*
|
||||||
|
* This function disconnects any active connections to supported joysticks.
|
||||||
|
* Applications must reconnect to the joystick using \ref libx52_connect prior
|
||||||
|
* to calling \ref libx52_update.
|
||||||
|
*
|
||||||
|
* @param[in] dev Pointer to the device
|
||||||
|
*
|
||||||
|
* @returns \ref libx52_error_code indicating status
|
||||||
|
*/
|
||||||
|
int libx52_disconnect(libx52_device *dev);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -70,6 +70,13 @@ int libx52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value)
|
||||||
int j;
|
int j;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
/* It is possible for the vendor command to be called when the joystick
|
||||||
|
* is not connected. Check for this and return an appropriate error.
|
||||||
|
*/
|
||||||
|
if (!x52->hdl) {
|
||||||
|
return LIBX52_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allow retry in case of failure */
|
/* Allow retry in case of failure */
|
||||||
for (j = 0; j < 3; j++) {
|
for (j = 0; j < 3; j++) {
|
||||||
rc = libusb_control_transfer(x52->hdl,
|
rc = libusb_control_transfer(x52->hdl,
|
||||||
|
@ -226,6 +233,13 @@ int libx52_update(libx52_device *x52)
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
int rc = LIBX52_SUCCESS;
|
int rc = LIBX52_SUCCESS;
|
||||||
|
|
||||||
|
/* It is possible for the update command to be called when the joystick
|
||||||
|
* is not connected. Check for this and return an appropriate error.
|
||||||
|
*/
|
||||||
|
if (!x52->hdl) {
|
||||||
|
return LIBX52_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Save the update mask */
|
/* Save the update mask */
|
||||||
update_mask = x52->update_mask;
|
update_mask = x52->update_mask;
|
||||||
/* Reset the device update mask to 0 */
|
/* Reset the device update mask to 0 */
|
||||||
|
|
|
@ -43,7 +43,22 @@ static int libx52_device_is_x52pro(uint16_t idProduct)
|
||||||
return (idProduct == X52_PROD_X52PRO);
|
return (idProduct == X52_PROD_X52PRO);
|
||||||
}
|
}
|
||||||
|
|
||||||
int libx52_init(libx52_device **dev)
|
int libx52_disconnect(libx52_device *dev)
|
||||||
|
{
|
||||||
|
if (!dev) {
|
||||||
|
return LIBX52_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dev->hdl) {
|
||||||
|
libusb_close(dev->hdl);
|
||||||
|
dev->hdl = NULL;
|
||||||
|
dev->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBX52_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libx52_connect(libx52_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
|
@ -52,6 +67,52 @@ int libx52_init(libx52_device **dev)
|
||||||
libusb_device *device;
|
libusb_device *device;
|
||||||
libusb_device_handle *hdl;
|
libusb_device_handle *hdl;
|
||||||
struct libusb_device_descriptor desc;
|
struct libusb_device_descriptor desc;
|
||||||
|
|
||||||
|
/* Make sure that we have a valid pointer */
|
||||||
|
if (!dev) {
|
||||||
|
return LIBX52_ERROR_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disconnect any existing handles. This will force libx52 to rescan the
|
||||||
|
* device list and bind to the first supported joystick, if any. If the
|
||||||
|
* joystick was unplugged between subsequent calls to this function, then
|
||||||
|
* it will return a No device error. This also means that a new device
|
||||||
|
* handle is cached in the device structure.
|
||||||
|
*/
|
||||||
|
(void)libx52_disconnect(dev);
|
||||||
|
|
||||||
|
count = libusb_get_device_list(dev->ctx, &list);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
device = list[i];
|
||||||
|
if (!libusb_get_device_descriptor(device, &desc)) {
|
||||||
|
if (libx52_check_product(desc.idVendor, desc.idProduct)) {
|
||||||
|
rc = libusb_open(device, &hdl);
|
||||||
|
if (rc) {
|
||||||
|
return libx52internal_translate_libusb_error(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->hdl = hdl;
|
||||||
|
|
||||||
|
if (libx52_device_is_x52pro(desc.idProduct)) {
|
||||||
|
set_bit(&(dev->flags), X52_FLAG_IS_PRO);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libusb_free_device_list(list, 1);
|
||||||
|
|
||||||
|
/* Make sure we actually have an X52 device detected */
|
||||||
|
if (!dev->hdl) {
|
||||||
|
return LIBX52_ERROR_NO_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBX52_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int libx52_init(libx52_device **dev)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
libx52_device *x52_dev;
|
libx52_device *x52_dev;
|
||||||
|
|
||||||
/* Make sure that we have a valid return pointer */
|
/* Make sure that we have a valid return pointer */
|
||||||
|
@ -67,9 +128,10 @@ int libx52_init(libx52_device **dev)
|
||||||
|
|
||||||
rc = libusb_init(&(x52_dev->ctx));
|
rc = libusb_init(&(x52_dev->ctx));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
rc = LIBX52_ERROR_INIT_FAILURE;
|
free(x52_dev);
|
||||||
goto err_recovery;
|
return LIBX52_ERROR_INIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000106)
|
#if defined(LIBUSB_API_VERSION) && (LIBUSB_API_VERSION >= 0x01000106)
|
||||||
/*
|
/*
|
||||||
* Use the libusb_set_option flag instead of libusb_set_debug. This
|
* Use the libusb_set_option flag instead of libusb_set_debug. This
|
||||||
|
@ -81,33 +143,11 @@ int libx52_init(libx52_device **dev)
|
||||||
libusb_set_debug(x52_dev->ctx, LIBUSB_LOG_LEVEL_WARNING);
|
libusb_set_debug(x52_dev->ctx, LIBUSB_LOG_LEVEL_WARNING);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
count = libusb_get_device_list(x52_dev->ctx, &list);
|
/* Try to connect to any supported joystick. It's OK if there aren't
|
||||||
for (i = 0; i < count; i++) {
|
* any available to connect to, subsequent calls to libx52_connect will
|
||||||
device = list[i];
|
* be used to open the device handle
|
||||||
if (!libusb_get_device_descriptor(device, &desc)) {
|
*/
|
||||||
if (libx52_check_product(desc.idVendor, desc.idProduct)) {
|
(void)libx52_connect(x52_dev);
|
||||||
rc = libusb_open(device, &hdl);
|
|
||||||
if (rc) {
|
|
||||||
rc = libx52internal_translate_libusb_error(rc);
|
|
||||||
goto err_recovery;
|
|
||||||
}
|
|
||||||
|
|
||||||
x52_dev->hdl = hdl;
|
|
||||||
|
|
||||||
if (libx52_device_is_x52pro(desc.idProduct)) {
|
|
||||||
set_bit(&(x52_dev->flags), X52_FLAG_IS_PRO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
libusb_free_device_list(list, 1);
|
|
||||||
|
|
||||||
/* Make sure we actually have an X52 device detected */
|
|
||||||
if (!x52_dev->hdl) {
|
|
||||||
rc = LIBX52_ERROR_NO_DEVICE;
|
|
||||||
goto err_recovery;
|
|
||||||
}
|
|
||||||
|
|
||||||
*dev = x52_dev;
|
*dev = x52_dev;
|
||||||
|
|
||||||
|
@ -115,15 +155,11 @@ int libx52_init(libx52_device **dev)
|
||||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
|
||||||
return LIBX52_SUCCESS;
|
return LIBX52_SUCCESS;
|
||||||
|
|
||||||
err_recovery:
|
|
||||||
free(x52_dev);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void libx52_exit(libx52_device *dev)
|
void libx52_exit(libx52_device *dev)
|
||||||
{
|
{
|
||||||
libusb_close(dev->hdl);
|
libx52_disconnect(dev);
|
||||||
libusb_exit(dev->ctx);
|
libusb_exit(dev->ctx);
|
||||||
|
|
||||||
/* Clear the memory to prevent reuse */
|
/* Clear the memory to prevent reuse */
|
||||||
|
|
|
@ -374,11 +374,18 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lookup the X52 device */
|
/* Initialize libx52 */
|
||||||
rc = libx52_init(&x52);
|
rc = libx52_init(&x52);
|
||||||
|
|
||||||
if (rc != LIBX52_SUCCESS) {
|
if (rc != LIBX52_SUCCESS) {
|
||||||
fprintf(stderr, "Error initializing X52 joystick: %s\n", libx52_strerror(rc));
|
fprintf(stderr, "Error initializing X52 library: %s\n", libx52_strerror(rc));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we are connected to the joystick */
|
||||||
|
rc = libx52_connect(x52);
|
||||||
|
if (rc != LIBX52_SUCCESS) {
|
||||||
|
fprintf(stderr, "Error connecting to joystick: %s\n", libx52_strerror(rc));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue