mirror of https://github.com/nirenjan/libx52.git
88 lines
2.1 KiB
C
88 lines
2.1 KiB
C
/*
|
|
* Saitek X52 Pro MFD & LED driver - Event handler
|
|
*
|
|
* Copyright (C) 2026 Nirenjan Krishnan (nirenjan@nirenjan.org)
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
|
|
*/
|
|
|
|
#include <stdatomic.h>
|
|
#include <errno.h>
|
|
|
|
#include "event_handler.h"
|
|
|
|
typedef struct {
|
|
_Atomic x52_event_handler_fn fn;
|
|
_Atomic uint64_t mask;
|
|
} x52_event_handler;
|
|
|
|
#define MAX_EVENT_HANDLERS 8
|
|
|
|
static x52_event_handler handlers[MAX_EVENT_HANDLERS];
|
|
static atomic_int num_handlers = 0;
|
|
|
|
int x52d_register_event_handler(uint64_t mask, x52_event_handler_fn fn)
|
|
{
|
|
int ticket;
|
|
|
|
if (fn == NULL) {
|
|
// Don't bother registering a NULL callback
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
ticket = atomic_fetch_add(&num_handlers, 1);
|
|
if (ticket >= MAX_EVENT_HANDLERS) {
|
|
// Already hit the maximum tickets
|
|
errno = ENOSPC;
|
|
return -1;
|
|
}
|
|
|
|
atomic_store(&handlers[ticket].mask, mask | LIBX52IO_REPORT_DEVICE_DISCONNECTED);
|
|
atomic_store(&handlers[ticket].fn, fn);
|
|
|
|
return ticket;
|
|
}
|
|
|
|
int x52d_update_event_handler_mask(int handler, uint64_t new_mask)
|
|
{
|
|
if (handler < 0 || handler >= MAX_EVENT_HANDLERS) {
|
|
errno = ERANGE;
|
|
return -1;
|
|
}
|
|
|
|
if (atomic_load(&handlers[handler].fn) == NULL) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
atomic_store(&handlers[handler].mask, new_mask);
|
|
return 0;
|
|
}
|
|
|
|
void x52d_dispatch_event(libx52io_report *prev, libx52io_report *curr)
|
|
{
|
|
uint64_t changed = libx52io_compare_reports(prev, curr);
|
|
x52d_dispatch_event_raw(changed, prev, curr);
|
|
}
|
|
|
|
void x52d_dispatch_event_raw(uint64_t changed, libx52io_report *prev, libx52io_report *curr)
|
|
{
|
|
int current_limit = atomic_load(&num_handlers);
|
|
if (current_limit >= MAX_EVENT_HANDLERS) {
|
|
current_limit = MAX_EVENT_HANDLERS;
|
|
}
|
|
|
|
for (int i = 0; i < current_limit; i++) {
|
|
x52_event_handler_fn callback = atomic_load(&handlers[i].fn);
|
|
if (callback == NULL) {
|
|
continue;
|
|
}
|
|
|
|
uint64_t mask = atomic_load(&handlers[i].mask) & changed;
|
|
if (mask != 0) {
|
|
callback(mask, prev, curr);
|
|
}
|
|
}
|
|
}
|