mirror of https://github.com/nirenjan/libx52.git
117 lines
3.2 KiB
C
117 lines
3.2 KiB
C
/*
|
|
* Saitek X52 Pro MFD & LED driver - I/O driver
|
|
*
|
|
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
|
|
#include "x52d_const.h"
|
|
#include "x52d_config.h"
|
|
#include "x52d_io.h"
|
|
#include "x52d_mouse.h"
|
|
#include "libx52io.h"
|
|
#include "pinelog.h"
|
|
|
|
static libx52io_context *io_ctx;
|
|
|
|
static pthread_t io_thr;
|
|
|
|
static void process_report(libx52io_report *report, libx52io_report *prev)
|
|
{
|
|
// TODO: Process changes
|
|
x52d_mouse_report_event(report);
|
|
memcpy(prev, report, sizeof(*prev));
|
|
}
|
|
|
|
static void *x52_io_thr(void *param)
|
|
{
|
|
int rc;
|
|
libx52io_report report;
|
|
libx52io_report prev_report;
|
|
bool connected = false;
|
|
|
|
#define IO_READ_TIMEOUT 50 /* milliseconds */
|
|
#define IO_ACQ_TIMEOUT 5 /* seconds */
|
|
PINELOG_INFO(_("Starting X52 I/O thread"));
|
|
|
|
// Reset the previous report, so that process_report can handle changes.
|
|
memset(&prev_report, 0, sizeof(prev_report));
|
|
|
|
for (;;) {
|
|
if (!connected) {
|
|
rc = libx52io_open(io_ctx);
|
|
if (rc == LIBX52IO_SUCCESS) {
|
|
connected = true;
|
|
} else {
|
|
if (rc != LIBX52IO_ERROR_NO_DEVICE) {
|
|
PINELOG_ERROR(_("Error %d opening X52 I/O device: %s"),
|
|
rc, libx52io_strerror(rc));
|
|
} else {
|
|
PINELOG_TRACE("No compatible X52 I/O device found. Waiting %d seconds before trying again.", IO_ACQ_TIMEOUT);
|
|
}
|
|
sleep(IO_ACQ_TIMEOUT);
|
|
}
|
|
} else {
|
|
rc = libx52io_read_timeout(io_ctx, &report, IO_READ_TIMEOUT);
|
|
switch (rc) {
|
|
case LIBX52IO_SUCCESS:
|
|
// Found a report
|
|
process_report(&report, &prev_report);
|
|
break;
|
|
|
|
case LIBX52IO_ERROR_TIMEOUT:
|
|
// No report received within the timeout
|
|
break;
|
|
|
|
case LIBX52IO_ERROR_NO_DEVICE:
|
|
PINELOG_TRACE("Device disconnected, signaling I/O connect thread");
|
|
/* Report a NULL report to reset the mouse to default state */
|
|
x52d_mouse_report_event(NULL);
|
|
connected = false;
|
|
break;
|
|
|
|
default:
|
|
PINELOG_ERROR(_("Error %d reading from X52 I/O device: %s"),
|
|
rc, libx52io_strerror(rc));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#undef IO_READ_TIMEOUT
|
|
#undef IO_ACQ_TIMEOUT
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void x52d_io_init(void)
|
|
{
|
|
int rc;
|
|
|
|
PINELOG_TRACE("Initializing I/O driver");
|
|
rc = libx52io_init(&io_ctx);
|
|
if (rc != LIBX52IO_SUCCESS) {
|
|
PINELOG_FATAL(_("Error %d initializing X52 I/O library: %s"),
|
|
rc, libx52io_strerror(rc));
|
|
}
|
|
|
|
rc = pthread_create(&io_thr, NULL, x52_io_thr, NULL);
|
|
if (rc != 0) {
|
|
PINELOG_FATAL(_("Error %d initializing I/O driver thread: %s"),
|
|
rc, strerror(rc));
|
|
}
|
|
}
|
|
|
|
void x52d_io_exit(void)
|
|
{
|
|
PINELOG_INFO(_("Shutting down X52 I/O driver thread"));
|
|
pthread_cancel(io_thr);
|
|
|
|
libx52io_exit(io_ctx);
|
|
}
|