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 <stefan11111@shitposting.expert>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This commit is contained in:
stefan11111
2025-07-06 01:54:48 +03:00
committed by Enrico Weigelt
parent 205c07979b
commit be7784fce2
2 changed files with 130 additions and 0 deletions

View File

@@ -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);

View File

@@ -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)
{