mirror of https://github.com/nirenjan/libx52.git
183 lines
5.3 KiB
C
183 lines
5.3 KiB
C
/*
|
|
* Saitek X52 Pro MFD & LED driver - Event test utility
|
|
*
|
|
* Copyright (C) 2012-2020 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <stdbool.h>
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
|
|
#include "libx52io.h"
|
|
#include "gettext.h"
|
|
|
|
/*
|
|
Output Format
|
|
=============
|
|
|
|
Driver version is 0.0.0
|
|
Device ID: bus 0x3 vendor 0x06a3 product 0x0762 version 0x110
|
|
Device name: "Saitek X52 Pro Flight Control System"
|
|
Testing ... (interrupt to exit)
|
|
|
|
Event @ 1594431236.817842, ABS_X, value 512
|
|
Event @ 1594431236.817842, ABS_Y, value 511
|
|
Event @ 1594431236.817842, BTN_TRIGGER, value 1
|
|
Event @ 1594431236.817842, BTN_MODE_1, value 1
|
|
|
|
Event @ 1594431236.847810, BTN_MODE_1, value 0
|
|
|
|
Event @ 1594431236.877802, BTN_MODE_2, value 1
|
|
|
|
*/
|
|
|
|
static bool exit_loop = false;
|
|
|
|
static void signal_handler(int sig)
|
|
{
|
|
exit_loop = true;
|
|
}
|
|
|
|
/* Denoising - reduce event noise due to adjacent values being reported */
|
|
static bool denoise = true;
|
|
|
|
/* For i18n */
|
|
#define _(x) gettext(x)
|
|
int main(int argc, char **argv)
|
|
{
|
|
libx52io_context *ctx;
|
|
libx52io_report last, curr;
|
|
int32_t denoise_mask[LIBX52IO_AXIS_MAX] = { 0 };
|
|
int rc;
|
|
#define CHECK_RC() do { \
|
|
if (rc != LIBX52IO_SUCCESS) { \
|
|
fprintf(stderr, "%s\n", libx52io_strerror(rc)); \
|
|
return rc; \
|
|
} \
|
|
} while(0)
|
|
|
|
/* Initialize gettext */
|
|
#if ENABLE_NLS
|
|
setlocale(LC_ALL, "");
|
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
|
textdomain(LOCALEDIR);
|
|
#endif
|
|
|
|
memset(&last, 0, sizeof(last));
|
|
memset(&curr, 0, sizeof(curr));
|
|
|
|
/* Initialize libx52io */
|
|
rc = libx52io_init(&ctx);
|
|
CHECK_RC();
|
|
|
|
/* Make sure that we have a device to connect to */
|
|
rc = libx52io_open(ctx);
|
|
CHECK_RC();
|
|
|
|
/* Initialize denoising */
|
|
if (denoise) {
|
|
for (int i = LIBX52IO_AXIS_X; i < LIBX52IO_AXIS_MAX; i++) {
|
|
int32_t min, max;
|
|
rc = libx52io_get_axis_range(ctx, i, &min, &max);
|
|
CHECK_RC();
|
|
|
|
/*
|
|
* Denoising algorithm ignores the last few bits of the axis,
|
|
* and is based on the maximum value of the axis. The mask is
|
|
* ~(max >> 6) which will do nothing for the axis with a small
|
|
* range, but reduce the noise on those with a larger range.
|
|
*/
|
|
denoise_mask[i] = ~(max >> 6);
|
|
}
|
|
}
|
|
|
|
/* Set up the signal handler to terminate the loop on SIGTERM or SIGINT */
|
|
exit_loop = false;
|
|
signal(SIGTERM, signal_handler);
|
|
signal(SIGINT, signal_handler);
|
|
|
|
/* Print the driver version and the connected device */
|
|
printf(_("Device ID: vendor 0x%04x product 0x%04x version 0x%04x\n"),
|
|
libx52io_get_vendor_id(ctx),
|
|
libx52io_get_product_id(ctx),
|
|
libx52io_get_device_version(ctx));
|
|
printf(_("Device name: \"%s %s\"\n"),
|
|
libx52io_get_manufacturer_string(ctx),
|
|
libx52io_get_product_string(ctx));
|
|
printf(_("Serial number: \"%s\"\n"), libx52io_get_serial_number_string(ctx));
|
|
puts(_("Testing (interrupt to exit)\n"));
|
|
|
|
/* Wait until we get an event */
|
|
while (!exit_loop) {
|
|
struct timeval tv;
|
|
bool printed = false;
|
|
|
|
/* Wait for 1 second before timing out */
|
|
rc = libx52io_read_timeout(ctx, &curr, 1000);
|
|
if (rc == LIBX52IO_ERROR_TIMEOUT) {
|
|
continue;
|
|
} else if (rc != LIBX52IO_SUCCESS) {
|
|
/* Some other error while reading. Abort the loop */
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Successful read, compare the current report against the previous
|
|
* one and display the result
|
|
*/
|
|
if (memcmp(&last, &curr, sizeof(curr)) == 0) {
|
|
/* No change, ignore the output */
|
|
continue;
|
|
}
|
|
|
|
/* Get the current timeval - we don't need a timezone */
|
|
gettimeofday(&tv, NULL);
|
|
for (int axis = 0; axis < LIBX52IO_AXIS_MAX; axis++) {
|
|
if (last.axis[axis] != curr.axis[axis]) {
|
|
/* Account for denoising */
|
|
if (denoise) {
|
|
int32_t last_v = last.axis[axis] & denoise_mask[axis];
|
|
int32_t curr_v = curr.axis[axis] & denoise_mask[axis];
|
|
|
|
if (last_v == curr_v) {
|
|
/* Within the noise threshold */
|
|
continue;
|
|
}
|
|
}
|
|
|
|
printf(_("Event @ %ld.%06ld: %s, value %d\n"),
|
|
(long int)tv.tv_sec, (long int)tv.tv_usec,
|
|
libx52io_axis_to_str(axis), curr.axis[axis]);
|
|
printed = true;
|
|
}
|
|
}
|
|
for (int btn = 0; btn < LIBX52IO_BUTTON_MAX; btn++) {
|
|
if (last.button[btn] != curr.button[btn]) {
|
|
printf(_("Event @ %ld.%06ld: %s, value %d\n"),
|
|
(long int)tv.tv_sec, (long int)tv.tv_usec,
|
|
libx52io_button_to_str(btn), curr.button[btn]);
|
|
printed = true;
|
|
}
|
|
}
|
|
|
|
if (printed) {
|
|
puts("");
|
|
}
|
|
|
|
memcpy(&last, &curr, sizeof(curr));
|
|
}
|
|
|
|
/* Close and exit the libx52io library */
|
|
libx52io_close(ctx);
|
|
libx52io_exit(ctx);
|
|
}
|