this post was submitted on 03 Oct 2025
6 points (100.0% liked)

Einfach posten

157 readers
19 users here now

Regeln

einfach posten! lass das hier deinen seelenmülleimer sein. muss nicht nur text sein, aber bei medien bitte auch darauf eingehen was man daran gut/schlecht/so mittel findet.

kein meme, porno, fetisch, gore oder nazi-zeug. kein betteln. keine wissenschaftsleugnung. keine posts über suizid. keine shitposts. und natürlich die goldene regel: kein arschloch sein.

founded 1 year ago
MODERATORS
 

ELECOM Trackball EX-G Modelle haben ein neues Chipset, das (mal wieder) die Anzahl Buttons falsch meldet. Für einige Chipsets gibt es dafür schon Workaround-Code im Linux Kernel. Wenn dein extra Button nicht geht, kannst Du seine Clicks mit diesem Beispiel C-Programm (kompilieren mit gcc) detektieren und vllt. irgendwas machen:

#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <linux/hiddev.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <spawn.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
#include <string.h>

void sigio_handler(int signo) {
    // Dummy handler to "nudge" the process
    //write(STDERR_FILENO, "SIGIO received\n", 15);
}

int main(int argc, char *argv[] /*, char *envp[]*/) {
    if (argc != 2 ) {
        printf("Usage: %s /dev/usb/hiddev?\nWhere \"?\" is a number.\n", argv[0]);
        return 1;
    }
    int fd = open(argv[1], O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }
    char *xdotoolargs[] = { "pxdotool", "key", "p", NULL };
    extern char **environ;
    struct hiddev_event ev;
    int buttonNr=0;
    bool pressed=false;
    int status=-1;
    pid_t pid;

    // Set up dummy SIGIO handler
    struct sigaction sa;
    sa.sa_handler = sigio_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    if (sigaction(SIGIO, &sa, NULL) < 0) {
        perror("sigaction");
        close(fd);
        return 1;
    }

    // Set ownership and signal
    if (fcntl(fd, F_SETOWN, getpid()) < 0) {
        perror("fcntl F_SETOWN");
        close(fd);
        return 1;
    }

    if (fcntl(fd, F_SETSIG, SIGIO) < 0) {
        perror("fcntl F_SETSIG");
        close(fd);
        return 1;
    }

    // Enable asynchronous I/O
    int flags = fcntl(fd, F_GETFL);
    if (fcntl(fd, F_SETFL, flags | O_ASYNC) < 0) {
        perror("fcntl F_SETFL O_ASYNC");
        close(fd);
        return 1;
    }

    int ev_size = sizeof(ev);
    while (1) {
        ssize_t n = read(fd, &ev, ev_size);
        if (n < 0 || n < ev_size) {
            if (errno == EINTR) continue; // Interrupted by signal
            perror("read");
            break;
        }
        if ( ev.hid == 589829) {
            if ( buttonNr == 1) {
                if ( ev.value == 1 ) {
                    if (!pressed) {
                        // extra button mouse down
                        printf(">>> HID event: button=%d, type=%d, value=%d\n",
                                            buttonNr,  ev.hid, ev.value);
                        fflush(stdout);
                        if(status==0){
                                waitpid(pid, &status, 0);
                        }
                        status = posix_spawn(&pid, "/usr/bin/xdotool", NULL, NULL, xdotoolargs, environ);
                        pressed=true;
                    }
                } else if(pressed) {
                    // extra button mouse up
                    //printf("<<< HID event: button=%d, type=%d, value=%d\n",
                    //                        buttonNr,  ev.hid, ev.value);
                    //fflush(stdout);
                    pressed=false;
                }
            //} else {
            //   // some other button with same event ID the kernel/X/wayland can handle (up or down)
            //   printf("--- HID event: button=%d, type=%d, value=%d\n",
            //                           buttonNr,  ev.hid, ev.value);
            //   fflush(stdout);
            }
            buttonNr++;
        } else {
            // more buttons or mouse events, but with different IDs
            //printf("    HID event: button=%d, type=%d, value=%d\n",
            //                        buttonNr,  ev.hid, ev.value);
            //fflush(stdout);
            buttonNr=0;
        }
    }
    if(status==0){
        waitpid(pid, &status, 0);
    }
    printf("Read all. Closing.");
    close(fd);
    return 0;
}

//edit: fixed read stalling after a while; launching xdotool as an example directly

no comments (yet)
sorted by: hot top controversial new old
there doesn't seem to be anything here