mirror of https://github.com/nirenjan/libx52.git
Add test cases for LEDs
This change adds tests for setting the X52Pro LEDs using the new x52 test infrastructure. This should be used in addition to the x52cli based test suite.pull/22/head
parent
92b0eb584f
commit
c96ba7fec4
|
@ -30,17 +30,21 @@ x52include_HEADERS = libx52.h
|
||||||
# pkg-config files
|
# pkg-config files
|
||||||
pkgconfig_DATA = libx52.pc
|
pkgconfig_DATA = libx52.pc
|
||||||
|
|
||||||
check_PROGRAMS = test_offset
|
check_PROGRAMS = test_offset test_led
|
||||||
|
|
||||||
test_offset_SOURCES = test_offset.c
|
test_offset_SOURCES = test_offset.c
|
||||||
test_offset_CFLAGS = @LIBUSB_CFLAGS@
|
test_offset_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
test_offset_LDADD = libx52.la
|
test_offset_LDADD = libx52.la
|
||||||
|
|
||||||
|
test_led_SOURCES = test_led.c test_common.c
|
||||||
|
test_led_CFLAGS = @LIBUSB_CFLAGS@
|
||||||
|
test_led_LDADD = libx52.la
|
||||||
|
|
||||||
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh
|
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh
|
||||||
TESTS = test_offset
|
TESTS = test_offset test_led
|
||||||
|
|
||||||
# Extra files that need to be in the distribution
|
# Extra files that need to be in the distribution
|
||||||
EXTRA_DIST = libx52.h x52_commands.h x52_common.h README.md
|
EXTRA_DIST = libx52.h x52_commands.h x52_common.h test_common.h README.md
|
||||||
|
|
||||||
# Add documentation files to the distribution
|
# Add documentation files to the distribution
|
||||||
EXTRA_DIST += \
|
EXTRA_DIST += \
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
/*
|
||||||
|
* Saitek X52 Pro MFD & LED driver
|
||||||
|
* Common functionality for test programs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "x52_common.h"
|
||||||
|
#include "test_common.h"
|
||||||
|
|
||||||
|
#define MAX_DIAGS 32
|
||||||
|
#define MAX_DIAG_SZ 256
|
||||||
|
static int diag_count;
|
||||||
|
static char diagnostic[MAX_DIAGS][MAX_DIAG_SZ];
|
||||||
|
|
||||||
|
#define ADD_DIAG(fmt_str, ...) do { \
|
||||||
|
if (diag_count < MAX_DIAGS) { \
|
||||||
|
snprintf(diagnostic[diag_count], MAX_DIAG_SZ, fmt_str, ##__VA_ARGS__); \
|
||||||
|
diag_count++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Test vendor command function */
|
||||||
|
int x52_test_vendor_command(libx52_device *dev, uint16_t index, uint16_t value)
|
||||||
|
{
|
||||||
|
struct x52_vendor_data *vdata = (struct x52_vendor_data *)dev->hdl;
|
||||||
|
struct ivpair data = {index, value};
|
||||||
|
|
||||||
|
if (vdata->written < MAX_SZ) {
|
||||||
|
vdata->data[vdata->written] = data;
|
||||||
|
vdata->written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBX52_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check expected data */
|
||||||
|
bool x52_test_assert_expected(libx52_device *dev, struct ivpair *data)
|
||||||
|
{
|
||||||
|
int written = 0;
|
||||||
|
struct x52_vendor_data *vdata = (struct x52_vendor_data *)dev->hdl;
|
||||||
|
|
||||||
|
while(data->index != 0 && data->value != 0 && written < vdata->written) {
|
||||||
|
if ((data->index != vdata->data[written].index) ||
|
||||||
|
(data->value != vdata->data[written].value)) {
|
||||||
|
ADD_DIAG("Mismatched data at position %d:", written);
|
||||||
|
ADD_DIAG("\tExpected: {%04x, %04x}", data->index, data->value);
|
||||||
|
ADD_DIAG("\tObserved: {%04x, %04x}", vdata->data[written].index, vdata->data[written].value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data++;
|
||||||
|
written++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->index != 0 || data->value != 0) {
|
||||||
|
ADD_DIAG("Insufficient data written, got only %d, additional expected:", written);
|
||||||
|
while (data->index != 0 && data->value != 0) {
|
||||||
|
ADD_DIAG("\t%04x %04x", data->index, data->value);
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vdata->written > written) {
|
||||||
|
ADD_DIAG("More data written, expected only %d, got %d", written, vdata->written);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void x52_test_print_diagnostics(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < diag_count; i++) {
|
||||||
|
printf("# %s\n", diagnostic[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize libx52, close any device handles, create a dummy handle
|
||||||
|
* and override the vendor command function.
|
||||||
|
*/
|
||||||
|
libx52_device *x52_test_init(void)
|
||||||
|
{
|
||||||
|
libx52_device *dev;
|
||||||
|
struct x52_vendor_data *vdata;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = libx52_init(&dev);
|
||||||
|
if (rc != LIBX52_SUCCESS) {
|
||||||
|
fputs(libx52_strerror(rc), stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)libx52_disconnect(dev);
|
||||||
|
|
||||||
|
/* Allocate memory for vendor data */
|
||||||
|
vdata = calloc(1, sizeof(*vdata));
|
||||||
|
if (vdata == NULL) {
|
||||||
|
perror("vendor data calloc");
|
||||||
|
libx52_exit(dev);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the diagnostics buffers */
|
||||||
|
memset(diagnostic, 0, sizeof(diagnostic));
|
||||||
|
diag_count = 0;
|
||||||
|
|
||||||
|
/* We don't need the device handle in test code, repurpose it */
|
||||||
|
dev->hdl = (libusb_device_handle *)vdata;
|
||||||
|
|
||||||
|
/* Setup vendor command function */
|
||||||
|
dev->vendor_cmd_fn = x52_test_vendor_command;
|
||||||
|
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void x52_test_cleanup(libx52_device *dev)
|
||||||
|
{
|
||||||
|
free(dev->hdl);
|
||||||
|
dev->hdl = NULL;
|
||||||
|
libx52_exit(dev);
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* Saitek X52 Pro MFD & LED driver
|
||||||
|
* Common functionality for test programs
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _TEST_COMMON_H
|
||||||
|
#define _TEST_COMMON_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "x52_common.h"
|
||||||
|
|
||||||
|
/* ivpair is a pair of index and value fields that are passed to the
|
||||||
|
* test vendor command function.
|
||||||
|
*/
|
||||||
|
struct ivpair {
|
||||||
|
uint16_t index;
|
||||||
|
uint16_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_SZ 100
|
||||||
|
struct x52_vendor_data {
|
||||||
|
int written;
|
||||||
|
struct ivpair data[MAX_SZ];
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize libx52, close any device handles, create a dummy handle
|
||||||
|
* and override the vendor command function.
|
||||||
|
*/
|
||||||
|
libx52_device *x52_test_init(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if expected data matches with written data. Terminate expected
|
||||||
|
* data with a pair of NULLs
|
||||||
|
*/
|
||||||
|
bool x52_test_assert_expected(libx52_device *dev, struct ivpair *data);
|
||||||
|
|
||||||
|
/* Print diagnostics to screen */
|
||||||
|
void x52_test_print_diagnostics(void);
|
||||||
|
|
||||||
|
/* Cleanup test data */
|
||||||
|
void x52_test_cleanup(libx52_device *dev);
|
||||||
|
|
||||||
|
#endif // !defined _TEST_COMMON_H
|
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* Saitek X52 Pro MFD & LED driver
|
||||||
|
* Test program for validating LED sets
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "x52_common.h"
|
||||||
|
#include "test_common.h"
|
||||||
|
#include "x52_commands.h"
|
||||||
|
|
||||||
|
struct test_case {
|
||||||
|
const char *test_case_id;
|
||||||
|
libx52_led_id led_id;
|
||||||
|
libx52_led_state state;
|
||||||
|
int retval;
|
||||||
|
struct ivpair data[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define X52_LED_CMD 0xb8
|
||||||
|
#define UNSUPPORTED(led, state) { #led "/" #state " unsupported", LIBX52_LED_ ## led, LIBX52_LED_STATE_ ## state, LIBX52_ERROR_NOT_SUPPORTED}
|
||||||
|
#define OFF_MONO(led) { #led "/Off", LIBX52_LED_## led, LIBX52_LED_STATE_OFF, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led) << 8)}, {0, 0}}}
|
||||||
|
#define ON(led) { #led "/On", LIBX52_LED_## led, LIBX52_LED_STATE_ON, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led) << 8) | 1}, {0, 0}}}
|
||||||
|
#define OFF_COLOR(led) { #led "/Off", LIBX52_LED_## led, LIBX52_LED_STATE_OFF, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8)}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8)}, {0, 0}}}
|
||||||
|
#define RED(led) { #led "/Red", LIBX52_LED_## led, LIBX52_LED_STATE_RED, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 1}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 0}, {0, 0}}}
|
||||||
|
#define AMBER(led) { #led "/Amber", LIBX52_LED_## led, LIBX52_LED_STATE_AMBER, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 1}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 1}, {0, 0}}}
|
||||||
|
#define GREEN(led) { #led "/Green", LIBX52_LED_## led, LIBX52_LED_STATE_GREEN, LIBX52_SUCCESS, {{X52_LED_CMD, ((LIBX52_LED_ ## led + 0) << 8) | 0}, {X52_LED_CMD, ((LIBX52_LED_ ## led + 1) << 8) | 1}, {0, 0}}}
|
||||||
|
|
||||||
|
const struct test_case test_cases[] = {
|
||||||
|
OFF_MONO(FIRE),
|
||||||
|
ON(FIRE),
|
||||||
|
UNSUPPORTED(FIRE, RED),
|
||||||
|
UNSUPPORTED(FIRE, AMBER),
|
||||||
|
UNSUPPORTED(FIRE, GREEN),
|
||||||
|
|
||||||
|
OFF_COLOR(A),
|
||||||
|
UNSUPPORTED(A, ON),
|
||||||
|
RED(A),
|
||||||
|
AMBER(A),
|
||||||
|
GREEN(A),
|
||||||
|
|
||||||
|
OFF_COLOR(B),
|
||||||
|
UNSUPPORTED(B, ON),
|
||||||
|
RED(B),
|
||||||
|
AMBER(B),
|
||||||
|
GREEN(B),
|
||||||
|
|
||||||
|
OFF_COLOR(D),
|
||||||
|
UNSUPPORTED(D, ON),
|
||||||
|
RED(D),
|
||||||
|
AMBER(D),
|
||||||
|
GREEN(D),
|
||||||
|
|
||||||
|
OFF_COLOR(E),
|
||||||
|
UNSUPPORTED(E, ON),
|
||||||
|
RED(E),
|
||||||
|
AMBER(E),
|
||||||
|
GREEN(E),
|
||||||
|
|
||||||
|
OFF_COLOR(T1),
|
||||||
|
UNSUPPORTED(T1, ON),
|
||||||
|
RED(T1),
|
||||||
|
AMBER(T1),
|
||||||
|
GREEN(T1),
|
||||||
|
|
||||||
|
OFF_COLOR(T2),
|
||||||
|
UNSUPPORTED(T2, ON),
|
||||||
|
RED(T2),
|
||||||
|
AMBER(T2),
|
||||||
|
GREEN(T2),
|
||||||
|
|
||||||
|
OFF_COLOR(T3),
|
||||||
|
UNSUPPORTED(T3, ON),
|
||||||
|
RED(T3),
|
||||||
|
AMBER(T3),
|
||||||
|
GREEN(T3),
|
||||||
|
|
||||||
|
OFF_COLOR(POV),
|
||||||
|
UNSUPPORTED(POV, ON),
|
||||||
|
RED(POV),
|
||||||
|
AMBER(POV),
|
||||||
|
GREEN(POV),
|
||||||
|
|
||||||
|
OFF_COLOR(CLUTCH),
|
||||||
|
UNSUPPORTED(CLUTCH, ON),
|
||||||
|
RED(CLUTCH),
|
||||||
|
AMBER(CLUTCH),
|
||||||
|
GREEN(CLUTCH),
|
||||||
|
|
||||||
|
OFF_MONO(THROTTLE),
|
||||||
|
ON(THROTTLE),
|
||||||
|
UNSUPPORTED(THROTTLE, RED),
|
||||||
|
UNSUPPORTED(THROTTLE, AMBER),
|
||||||
|
UNSUPPORTED(THROTTLE, GREEN),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TC_COUNT (sizeof(test_cases) / sizeof(test_cases[0]))
|
||||||
|
|
||||||
|
void run_test(int tc_id)
|
||||||
|
{
|
||||||
|
struct libx52_device *dev = x52_test_init();
|
||||||
|
|
||||||
|
struct test_case test = test_cases[tc_id];
|
||||||
|
|
||||||
|
/* Set the X52Pro flag in dev->flags, otherwise libx52_set_led_state will
|
||||||
|
* always return not supported
|
||||||
|
*/
|
||||||
|
dev->flags = 1;
|
||||||
|
|
||||||
|
#define PRINT_FAIL() printf("not ok %d %s\n", tc_id+1, test.test_case_id)
|
||||||
|
#define PRINT_PASS() printf("ok %d %s\n", tc_id+1, test.test_case_id)
|
||||||
|
int rc = libx52_set_led_state(dev, test.led_id, test.state);
|
||||||
|
|
||||||
|
if (rc != test.retval) {
|
||||||
|
PRINT_FAIL();
|
||||||
|
printf("# Expected retval %d, got %d\n", test.retval, rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = libx52_update(dev);
|
||||||
|
if (rc != LIBX52_SUCCESS) {
|
||||||
|
PRINT_FAIL();
|
||||||
|
printf("# libx52_update failed, rc = %d\n", rc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!x52_test_assert_expected(dev, test.data)) {
|
||||||
|
PRINT_FAIL();
|
||||||
|
x52_test_print_diagnostics();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRINT_PASS();
|
||||||
|
x52_test_cleanup(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf("1..%ld\n", TC_COUNT);
|
||||||
|
for (i = 0; i < TC_COUNT; i++) {
|
||||||
|
run_test(i);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue