Posts
Search
Contact
Cookies
About
RSS

Joystick emulating keyboard

Added 21 Apr 2022, 7:14 p.m. edited 18 Jun 2023, 1:12 a.m.

Being somewhat frustrated with the input option available in a game I'm playing I quickly cobbled together a quick app to send key presses when the joystick is used.

The source below assumes WASD keys should be pressed when axis 0/1 changes and that buttons 0,1, and 2 should press keys Z, X and C.

Use entirely at your own risk, you should be able to see how to simply tailor it to your own use...

/* Makefile

CC = gcc
CFLAGS = -lX11 -lXtst
INCLUDES = 

keystick: keystick.o
    $(CC) $(CFLAGS) $(INCLUDES) keystick.o -o keystick 

keystick.o: main.c
    $(CC) $(CFLAGS) $(INCLUDES) -c main.c -o keystick.o  

*/

#include "stdio.h"
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <linux/joystick.h>
#include <fcntl.h>

#include <unistd.h>

Display *display=NULL;

#define JS_EVENT_BUTTON         0x01    /* button pressed/released */
#define JS_EVENT_AXIS           0x02    /* joystick moved */
#define JS_EVENT_INIT           0x80    /* initial state of device */
 
// TODO change for args
char target[] = "/dev/input/js0";

/*
struct js_event {
        __u32 time;     // event timestamp in milliseconds 
        __s16 value;    // value 
        __u8 type;      // event type 
        __u8 number;    // axis/button number 
};
*/

int main()
{
    struct js_event e;
    unsigned int keycodeZ;
    unsigned int keycodeX;
    unsigned int keycodeC;
    unsigned int keycodeW;
    unsigned int keycodeA;
    unsigned int keycodeS;
    unsigned int keycodeD;
    
    display = XOpenDisplay(NULL);
    keycodeZ = XKeysymToKeycode(display, XK_Z);
    keycodeX = XKeysymToKeycode(display, XK_X);
    keycodeC = XKeysymToKeycode(display, XK_C);
    keycodeW = XKeysymToKeycode(display, XK_W);
    keycodeA = XKeysymToKeycode(display, XK_A);
    keycodeS = XKeysymToKeycode(display, XK_S);
    keycodeD = XKeysymToKeycode(display, XK_D);
    
    int xactive = 0;
    int yactive = 0;
        
    int fd = open (target, O_RDONLY);
    
    while(1) {
        read (fd, &e, sizeof(e));
        //printf("%i\t\t%i\t\t%i\n", e.value, e.type, e.number);
        if (e.type == JS_EVENT_BUTTON) {
            unsigned int kk = -1;
            if (e.number == 0) { kk = keycodeC; }
            if (e.number == 1) { kk = keycodeX; }
            if (e.number == 2) { kk = keycodeZ; }
            if (kk!=-1) {
                XTestFakeKeyEvent(display, kk, e.value, 0);
                XFlush(display);
            }
        }
        
        if (e.type==JS_EVENT_AXIS) {
            if (e.number==0) {
                // x axis
                if (e.value > -16000 && e.value < 16000) {
                    XTestFakeKeyEvent(display, keycodeA, False, 0);
                    XTestFakeKeyEvent(display, keycodeD, False, 0);
                }

                if (e.value > 16000) {
                    XTestFakeKeyEvent(display, keycodeD, True, 0);
                }
                
                if (e.value < -16000) {
                    XTestFakeKeyEvent(display, keycodeA, True, 0);
                }
            }
            
            if (e.number==1) {
                // y axis
                if (e.value > -16000 && e.value < 16000) {
                    XTestFakeKeyEvent(display, keycodeW, False, 0);
                    XTestFakeKeyEvent(display, keycodeS, False, 0);
                }

                if (e.value > 16000) {
                    XTestFakeKeyEvent(display, keycodeS, True, 0);
                }
                
                if (e.value < -16000) {
                    XTestFakeKeyEvent(display, keycodeW, True, 0);
                }
            }
            XFlush(display);
        }
    }

    return 0;
}

Enjoy!