/* * 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 #include #include #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); }