From be7784fce269160bfea312e0a76ec1ef240b5f69 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sun, 6 Jul 2025 01:54:48 +0300 Subject: [PATCH] kdrive: add fd notification machinery This will be needed by Xfbdev's keyboard driver, which cannot work with input threads yet. Signed-off-by: stefan11111 Signed-off-by: Enrico Weigelt, metux IT consult --- hw/kdrive/src/kdrive.h | 6 ++ hw/kdrive/src/kinput.c | 124 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index 37672cd757..b709945aaf 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -431,6 +431,12 @@ void void KdCloseInput(void); +Bool KdRegisterFd(int fd, void (*read) (int fd, void *closure), void *closure); + +void KdUnregisterFds(void *closure, Bool do_close); + +void KdUnregisterFd(void *closure, int fd, Bool do_close); + void KdEnqueueKeyboardEvent(KdKeyboardInfo * ki, unsigned char scan_code, unsigned char is_up); diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c index c94a3f4cff..65e66871c8 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -77,6 +77,22 @@ static KdPointerMatrix kdPointerMatrix = { {0, 1, 0}} }; +#define KD_MAX_INPUT_FDS 8 + +typedef struct _kdInputFd { + int fd; + void (*read) (int fd, void *closure); + int (*enable) (int fd, void *closure); + void (*disable) (int fd, void *closure); + void *closure; +} KdInputFd; + +static KdInputFd kdInputFds[KD_MAX_INPUT_FDS]; +static int kdNumInputFds = 0; +#ifdef KDRIVE_KBD +static int kdnFds = 0; +#endif + extern Bool kdRawPointerCoordinates; extern const char *kdGlobalXkbRules; @@ -85,6 +101,14 @@ extern const char *kdGlobalXkbLayout; extern const char *kdGlobalXkbVariant; extern const char *kdGlobalXkbOptions; +#ifdef KDRIVE_KBD +static void KdSigio(int sig) +{ + for (int i = 0; i < kdNumInputFds; i++) + (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); +} +#endif + #ifdef FNONBLOCK #define NOBLOCK FNONBLOCK #else @@ -102,6 +126,106 @@ KdResetInputMachine(void) } } +static void KdNonBlockFd(int fd) +{ +#ifndef WIN32 + int flags = fcntl(fd, F_GETFL); + flags |= FASYNC | NOBLOCK; + fcntl(fd, F_SETFL, flags); +#endif +} + +static void KdNotifyFd(int fd, int ready, void *data) +{ + int i = (int) (intptr_t) data; + (*kdInputFds[i].read)(fd, kdInputFds[i].closure); +} + +static void KdAddFd(int fd, int i) +{ +#ifdef KDRIVE_KBD + struct sigaction act; + + sigset_t set; + + kdnFds++; + fcntl(fd, F_SETOWN, getpid()); +#endif + KdNonBlockFd(fd); + InputThreadRegisterDev(fd, KdNotifyFd, (void *) (intptr_t) i); +#ifdef KDRIVE_KBD + memset(&act, '\0', sizeof act); + act.sa_handler = KdSigio; + + sigemptyset(&act.sa_mask); + sigaddset(&act.sa_mask, SIGIO); + sigaddset(&act.sa_mask, SIGALRM); + sigaddset(&act.sa_mask, SIGVTALRM); + sigaction(SIGIO, &act, 0); + sigemptyset(&set); + sigprocmask(SIG_SETMASK, &set, 0); +#endif +} + +static void KdRemoveFd(int fd) +{ + InputThreadUnregisterDev(fd); +#ifndef WIN32 + int flags = fcntl(fd, F_GETFL); + flags &= ~(FASYNC | NOBLOCK); + fcntl(fd, F_SETFL, flags); +#endif +#ifdef KDRIVE_KBD + struct sigaction act; + kdnFds--; + if (kdnFds == 0) { + memset(&act, '\0', sizeof act); + act.sa_handler = SIG_IGN; + sigemptyset(&act.sa_mask); + sigaction(SIGIO, &act, 0); + } +#endif +} + +Bool KdRegisterFd(int fd, void (*read) (int fd, void *closure), void *closure) +{ + if (kdNumInputFds == KD_MAX_INPUT_FDS) + return FALSE; + kdInputFds[kdNumInputFds].fd = fd; + kdInputFds[kdNumInputFds].read = read; + kdInputFds[kdNumInputFds].enable = 0; + kdInputFds[kdNumInputFds].disable = 0; + kdInputFds[kdNumInputFds].closure = closure; + if (kdInputEnabled) + KdAddFd(fd, kdNumInputFds); + kdNumInputFds++; + return TRUE; +} + +void KdUnregisterFd(void *closure, int fd, Bool do_close) +{ + int i, j; + + for (i = 0; i < kdNumInputFds; i++) { + if (kdInputFds[i].closure == closure && + (fd == -1 || kdInputFds[i].fd == fd)) { + if (kdInputEnabled) + KdRemoveFd(kdInputFds[i].fd); + if (do_close) + close(kdInputFds[i].fd); + for (j = i; j < (kdNumInputFds - 1); j++) + kdInputFds[j] = kdInputFds[j + 1]; + kdNumInputFds--; + break; + } + } +} + +void KdUnregisterFds(void *closure, Bool do_close) +{ + KdUnregisterFd(closure, -1, do_close); +} + void KdDisableInput(void) {