API change for libx52

- libx52_init returns the libx52_device in an output parameter and
  returns a libx52_error_code
- Make all functions return libx52_error_code
- Update package version to indicate incompatible API change
feature/test-new-mem-api
nirenjan 2017-08-23 19:30:35 -07:00
parent fb222dda89
commit f3270def9d
10 changed files with 130 additions and 85 deletions

View File

@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based upon [Keep a Changelog].
## [Unreleased]
### Changed
- `libx52_init` now returns a `libx52_error_code`, and returns the
`libx52_device` pointer in an output parameter.
- All libx52 APIs now return a `libx52_error_code` indicating the error.
## [0.1.2] - 2017-08-17
### Added

View File

@ -1,4 +1,4 @@
AC_INIT([x52pro-linux], [0.1.2], [nirenjan@gmail.com])
AC_INIT([x52pro-linux], [0.2.0], [nirenjan@gmail.com])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AC_PROG_CC

View File

@ -5,7 +5,7 @@ lib_LTLIBRARIES = libx52.la
# Core libx52 library
# This library handles the USB communication between the host and the X52
libx52_la_SOURCES = x52_control.c x52_core.c x52_date_time.c x52_mfd_led.c
libx52_la_LDFLAGS = -version-info 3:0:2 -lusb-1.0
libx52_la_LDFLAGS = -version-info 4:0:2 -lusb-1.0
# Header files that need to be copied
x52includedir = $(includedir)/x52pro

View File

@ -1,7 +1,7 @@
/*
* Saitek X52 Pro MFD & LED driver
*
* Copyright (C) 2012-2015 Nirenjan Krishnan (nirenjan@nirenjan.org)
* Copyright (C) 2012-2017 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -131,6 +131,37 @@ typedef enum {
LIBX52_LED_STATE_GREEN,
} libx52_led_state;
/**
* @brief LibX52 Error codes
*
* Error codes returned by libx52
*/
typedef enum {
/** No error, indicates success */
LIBX52_SUCCESS = 0,
/** Initialization failure */
LIBX52_ERROR_INIT_FAILURE,
/** Out of memory */
LIBX52_ERROR_OUT_OF_MEMORY,
/** Invalid parameter(s) */
LIBX52_ERROR_INVALID_PARAM,
/** Not supported */
LIBX52_ERROR_NOT_SUPPORTED,
/** No change necessary, try again */
LIBX52_ERROR_TRY_AGAIN,
/** Clock timezone out of range */
LIBX52_ERROR_OUT_OF_RANGE,
/** Error encountered during USB interaction */
LIBX52_ERROR_USB_FAILURE,
} libx52_error_code;
/**
* @brief Initialize the X52 library
*
@ -144,9 +175,11 @@ typedef enum {
* This function does not support hotplugging. The joystick must be plugged in
* before calling this function.
*
* @returns a pointer to the detected \ref libx52_device
* @param[out] dev Pointer to a \ref libx52_device *
*
* @returns \ref libx52_error_code indicating status
*/
libx52_device * libx52_init(void);
int libx52_init(libx52_device ** dev);
/**
* @brief Exit the library and free up any resources used
@ -183,8 +216,8 @@ void libx52_exit(libx52_device *dev);
* the code page of the X52 display.
* @param[in] length Length of the text to display
*
* @returns 0 on success, \c -EINVAL if either \p x52 is invalid, or \p line is
* outside the accepted range.
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if either \p x52 is
* invalid, or \p line is outside the accepted range.
*/
int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t length);
@ -204,10 +237,11 @@ int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t
* @param[in] led LED identifier (refer \ref libx52_led_id)
* @param[in] state State of the LED (refer \ref libx52_led_state)
*
* @returns 0 on success, \c -EINVAL if the \p x52 parameter is not valid, and
* \c -ENOTSUP if the \p led and \p state combination is not a supported one.
* The API also returns \c -ENOTSUP if the probed joystick is not an X52 Pro,
* but the non-Pro X52 variant.
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if the \p x52
* parameter is not valid, and \ref LIBX52_ERROR_NOT_SUPPORTED if the \p led
* and \p state combination is not a supported one. The API also returns \ref
* LIBX52_ERROR_NOT_SUPPORTED if the probed joystick is not an X52 Pro, but the
* non-Pro X52 variant.
*/
int libx52_set_led_state(libx52_device *x52,
libx52_led_id led,
@ -221,11 +255,11 @@ int libx52_set_led_state(libx52_device *x52,
* whether the primary clock displays local time or GMT.
*
* If this function is called again within the same minute as calculated by
* \c localtime(3) or \c gmtime(3), it will return \c -EAGAIN, as it does not
* require any updates to be written to the joystick. However, if the call
* changes the timezone from local time to GMT or vice-versa, then the function
* will return 0, since it requires a write to the device to update the clock
* with the new timezone.
* \c localtime(3) or \c gmtime(3), it will return \ref LIBX52_ERROR_TRY_AGAIN,
* as it does not require any updates to be written to the joystick. However,
* if the call changes the timezone from local time to GMT or vice-versa, then
* the function will return 0, since it requires a write to the device to
* update the clock with the new timezone.
*
* The secondary and tertiary clocks are driven off the primary clock and set
* using \ref libx52_set_clock_timezone.
@ -234,8 +268,8 @@ int libx52_set_led_state(libx52_device *x52,
* @param[in] time Time value from \c time(3)
* @param[in] local 0 for GM time, non-zero for localtime
*
* @returns 0 on success, \c -EAGAIN if no change from previous time,
* \c -EINVAL if \p x52 is not valid.
* @returns 0 on success, \ref LIBX52_ERROR_TRY_AGAIN if no change from previous
* time, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid.
*/
int libx52_set_clock(libx52_device *x52, time_t time, int local);
@ -247,7 +281,7 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local);
* However, for convenience, the X52 library calculates this offset internally
* and only requires you to set the timezone as the number of minutes offset
* from GMT. \p offset is limited to +/- 1440 minutes, and any offset outside
* this range will result in a return value of \c -EDOM
* this range will result in a return value of \ref LIBX52_ERROR_OUT_OF_RANGE
*
* @param[in] x52 Pointer to the device
* @param[in] clock \ref libx52_clock_id, cannot be \ref
@ -255,9 +289,9 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local);
* @param[in] offset Offset in minutes from GMT (east is positive, west
* is negative)
*
* @returns 0 on success, \c -EINVAL if \p x52 is invalid, \c -ENOTSUP if
* \p clock is \ref LIBX52_CLOCK_1, \c -EDOM if \p offset is more than +/-
* 24 hours.
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is invalid,
* \ref LIBX52_ERROR_NOT_SUPPORTED if \p clock is \ref LIBX52_CLOCK_1, \ref
* LIBX52_ERROR_OUT_OF_RANGE if \p offset is more than +/- 24 hours.
*/
int libx52_set_clock_timezone(libx52_device *x52,
libx52_clock_id clock,
@ -278,8 +312,8 @@ int libx52_set_clock_timezone(libx52_device *x52,
* @param[in] clock \ref libx52_clock_id
* @param[in] format \ref libx52_clock_format
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid, or if either of
* \p clock or \p format are outside their respective ranges.
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid,
* or if either of \p clock or \p format are outside their respective ranges.
*/
int libx52_set_clock_format(libx52_device *x52,
libx52_clock_id clock,
@ -296,7 +330,7 @@ int libx52_set_clock_format(libx52_device *x52,
* @param[in] hour Hour to display
* @param[in] minute Minute to display
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid
*/
int libx52_set_time(libx52_device *x52, uint8_t hour, uint8_t minute);
@ -311,7 +345,7 @@ int libx52_set_time(libx52_device *x52, uint8_t hour, uint8_t minute);
* @param[in] mm Month to display
* @param[in] yy Year to display
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid
*/
int libx52_set_date(libx52_device *x52, uint8_t dd, uint8_t mm, uint8_t yy);
@ -323,7 +357,7 @@ int libx52_set_date(libx52_device *x52, uint8_t dd, uint8_t mm, uint8_t yy);
* @param[in] x52 Pointer to the device
* @param[in] format \ref libx52_date_format
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid
*/
int libx52_set_date_format(libx52_device *x52, libx52_date_format format);
@ -339,7 +373,7 @@ int libx52_set_date_format(libx52_device *x52, libx52_date_format format);
* @param[in] mfd 0 for LED brightness, 1 for MFD brightness
* @param[in] brightness Brightness level to set
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid.
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid.
*/
int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness);
@ -352,7 +386,7 @@ int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness);
* @param[in] x52 Pointer to the device
* @param[in] state 0 for off, 1 for on
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid
*/
int libx52_set_shift(libx52_device *x52, uint8_t state);
@ -364,7 +398,7 @@ int libx52_set_shift(libx52_device *x52, uint8_t state);
* @param[in] x52 Pointer to the device
* @param[in] state 0 for off, 1 for on
*
* @returns 0 on success, \c -EINVAL if \p x52 is not valid
* @returns 0 on success, \ref LIBX52_ERROR_INVALID_PARAM if \p x52 is not valid
*/
int libx52_set_blink(libx52_device *x52, uint8_t state);
@ -377,7 +411,7 @@ int libx52_set_blink(libx52_device *x52, uint8_t state);
*
* @param[in] x52 Pointer to the device
*
* @returns 0 on success, non-zero error number on failure
* @returns 0 on success, \ref LIBX52_ERROR_USB_FAILURE on failure
*/
int libx52_update(libx52_device *x52);
@ -394,7 +428,7 @@ int libx52_update(libx52_device *x52);
* @param[in] index wIndex in the USB packet
* @param[in] value wValue in the USB packet
*
* @returns 0 on success, non-zero error number on failure
* @returns 0 on success, \ref LIBX52_ERROR_USB_FAILURE on failure
*/
int libx52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value);

View File

@ -30,12 +30,16 @@ int libx52_vendor_command(libx52_device *x52, uint16_t index, uint16_t value)
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
X52_VENDOR_REQUEST, value, index, NULL, 0, 5000);
if (rc == 0) {
if (rc == LIBUSB_SUCCESS) {
break;
}
}
return rc;
if (rc == LIBUSB_SUCCESS) {
return LIBX52_SUCCESS;
} else {
return LIBX52_ERROR_USB_FAILURE;
}
}
static int libx52_write_line(libx52_device *x52, uint8_t line_index)
@ -97,11 +101,11 @@ static int libx52_write_date(libx52_device *x52)
break;
default:
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
rc = libx52_vendor_command(x52, X52_DATE_DDMM, value1);
if (rc == 0) {
if (rc == LIBX52_SUCCESS) {
rc = libx52_vendor_command(x52, X52_DATE_YEAR, value2);
}
@ -168,7 +172,7 @@ int libx52_update(libx52_device *x52)
unsigned int i;
uint32_t update_mask;
uint16_t value;
int rc = 0;
int rc = LIBX52_SUCCESS;
/* Save the update mask */
update_mask = x52->update_mask;
@ -221,7 +225,8 @@ int libx52_update(libx52_device *x52)
break;
case X52_BIT_POV_BLINK:
value = tst_bit(&x52->led_mask, X52_BIT_POV_BLINK) ? X52_BLINK_ON : X52_BLINK_OFF;
value = tst_bit(&x52->led_mask, X52_BIT_POV_BLINK)
? X52_BLINK_ON : X52_BLINK_OFF;
rc = libx52_vendor_command(x52, X52_BLINK_INDICATOR, value);
break;
@ -253,11 +258,11 @@ int libx52_update(libx52_device *x52)
default:
/* Ignore any spurious bits */
rc = 0;
rc = LIBX52_SUCCESS;
break;
}
if (rc == 0) {
if (rc == LIBX52_SUCCESS) {
clr_bit(&update_mask, i);
} else {
/* Last transfer failed - reset the update mask */

View File

@ -45,7 +45,7 @@ static int libx52_device_is_x52pro(uint16_t idProduct)
return (idProduct == X52_PROD_X52PRO);
}
libx52_device* libx52_init(void)
int libx52_init(libx52_device **dev)
{
int rc;
ssize_t count;
@ -56,20 +56,20 @@ libx52_device* libx52_init(void)
struct libusb_device_descriptor desc;
libx52_device *x52_dev;
/* Make sure that we have a valid return pointer */
if (dev == NULL) {
return LIBX52_ERROR_INVALID_PARAM;
}
/* Allocate memory for the library's data structures */
x52_dev = calloc(1, sizeof(libx52_device));
if (!x52_dev) {
errno = ENOMEM;
return NULL;
return LIBX52_ERROR_OUT_OF_MEMORY;
}
rc = libusb_init(&(x52_dev->ctx));
if (rc) {
#if defined(__linux__)
errno = ELIBACC;
#else
errno = ENOENT;
#endif
rc = LIBX52_ERROR_INIT_FAILURE;
goto err_recovery;
}
libusb_set_debug(x52_dev->ctx, LIBUSB_LOG_LEVEL_WARNING);
@ -100,10 +100,12 @@ libx52_device* libx52_init(void)
goto err_recovery;
}
return x52_dev;
*dev = x52_dev;
return LIBX52_SUCCESS;
err_recovery:
free(x52_dev);
return NULL;
return rc;
}
void libx52_exit(libx52_device *dev)

View File

@ -31,7 +31,7 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local)
int update_required = 0;
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (local) {
@ -78,26 +78,26 @@ int libx52_set_clock(libx52_device *x52, time_t time, int local)
/* Save the timezone */
x52->timezone[LIBX52_CLOCK_1] = local_tz;
return (update_required ? 0 : -EAGAIN);
return (update_required ? LIBX52_SUCCESS : LIBX52_ERROR_TRY_AGAIN);
}
int libx52_set_time(libx52_device *x52, uint8_t hour, uint8_t minute)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
x52->time_hour = hour;
x52->time_minute = minute;
set_bit(&x52->update_mask, X52_BIT_MFD_TIME);
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_date(libx52_device *x52, uint8_t dd, uint8_t mm, uint8_t yy)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
x52->date_day = dd;
@ -105,18 +105,18 @@ int libx52_set_date(libx52_device *x52, uint8_t dd, uint8_t mm, uint8_t yy)
x52->date_year = yy;
set_bit(&x52->update_mask, X52_BIT_MFD_DATE);
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_clock_timezone(libx52_device *x52, libx52_clock_id clock, int offset)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
/* Limit offset to +/- 24 hours */
if (offset < -1440 || offset > 1440) {
return -EDOM;
return LIBX52_ERROR_OUT_OF_RANGE;
}
switch (clock) {
@ -131,10 +131,10 @@ int libx52_set_clock_timezone(libx52_device *x52, libx52_clock_id clock, int off
break;
default:
return -ENOTSUP;
return LIBX52_ERROR_NOT_SUPPORTED;
}
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_clock_format(libx52_device *x52,
@ -142,13 +142,13 @@ int libx52_set_clock_format(libx52_device *x52,
libx52_clock_format format)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if ((format != LIBX52_CLOCK_FORMAT_12HR) &&
(format != LIBX52_CLOCK_FORMAT_24HR)) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
switch (clock) {
@ -165,20 +165,20 @@ int libx52_set_clock_format(libx52_device *x52,
break;
default:
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
x52->time_format[clock] = format;
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_date_format(libx52_device *x52, libx52_date_format format)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
x52->date_format = format;
set_bit(&x52->update_mask, X52_BIT_MFD_DATE);
return 0;
return LIBX52_SUCCESS;
}

View File

@ -20,11 +20,11 @@
int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t length)
{
if (!x52 || !text) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (line > 2) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (length > X52_MFD_LINE_SIZE) {
@ -36,13 +36,13 @@ int libx52_set_text(libx52_device *x52, uint8_t line, const char *text, uint8_t
x52->line[line].length = length;
set_bit(&x52->update_mask, X52_BIT_MFD_LINE1 + line);
return 0;
return LIBX52_SUCCESS;
}
static int x52pro_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state state)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
switch (led) {
@ -56,7 +56,7 @@ static int x52pro_set_led_state(libx52_device *x52, libx52_led_id led, libx52_le
set_bit(&x52->update_mask, led);
} else {
/* Colors not supported */
return -ENOTSUP;
return LIBX52_ERROR_NOT_SUPPORTED;
}
break;
@ -88,7 +88,7 @@ static int x52pro_set_led_state(libx52_device *x52, libx52_led_id led, libx52_le
default:
/* Cannot set the LED to "ON" */
return -ENOTSUP;
return LIBX52_ERROR_NOT_SUPPORTED;
}
/* Set the update mask bits */
@ -97,13 +97,13 @@ static int x52pro_set_led_state(libx52_device *x52, libx52_led_id led, libx52_le
break;
}
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state state)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (tst_bit(&x52->flags, X52_FLAG_IS_PRO)) {
@ -114,13 +114,13 @@ int libx52_set_led_state(libx52_device *x52, libx52_led_id led, libx52_led_state
* For now, we only support setting the LEDs on the X52 Pro model.
* Calling this API on a non-Pro model will return a not supported error.
*/
return -ENOTSUP;
return LIBX52_ERROR_NOT_SUPPORTED;
}
int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (mfd) {
@ -131,13 +131,13 @@ int libx52_set_brightness(libx52_device *x52, uint8_t mfd, uint16_t brightness)
set_bit(&x52->update_mask, X52_BIT_BRI_LED);
}
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_shift(libx52_device *x52, uint8_t state)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (state) {
@ -147,13 +147,13 @@ int libx52_set_shift(libx52_device *x52, uint8_t state)
}
set_bit(&x52->update_mask, X52_BIT_SHIFT);
return 0;
return LIBX52_SUCCESS;
}
int libx52_set_blink(libx52_device *x52, uint8_t state)
{
if (!x52) {
return -EINVAL;
return LIBX52_ERROR_INVALID_PARAM;
}
if (state) {
@ -163,5 +163,5 @@ int libx52_set_blink(libx52_device *x52, uint8_t state)
}
set_bit(&x52->update_mask, X52_BIT_POV_BLINK);
return 0;
return LIBX52_SUCCESS;
}

View File

@ -442,9 +442,9 @@ int main(int argc, char **argv)
}
/* Lookup the X52 device */
x52 = libx52_init();
rc = libx52_init(&x52);
if (!x52) {
if (rc != LIBX52_SUCCESS) {
fprintf(stderr, "Unable to find X52 joystick!\n");
return 1;
}

View File

@ -109,8 +109,8 @@ static int run_tests(int test_set)
getc(stdin);
dev = libx52_init();
if (dev == NULL) {
rc = libx52_init(&dev);
if (rc != LIBX52_SUCCESS) {
fprintf(stderr, "Unable to connect to X52 Pro Joystick!\n");
return 1;
}