Skip to content

Instantly share code, notes, and snippets.

@BioBoost
Forked from jasonwhite/joystick.c
Created June 9, 2022 05:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BioBoost/053fb2d5da878e5216cabb9f1bad93d8 to your computer and use it in GitHub Desktop.
Save BioBoost/053fb2d5da878e5216cabb9f1bad93d8 to your computer and use it in GitHub Desktop.
Reads joystick/gamepad events on Linux and displays them.
/**
* Author: Jason White
*
* Description:
* Reads joystick/gamepad events and displays them.
*
* Compile:
* gcc joystick.c -o joystick
*
* Run:
* ./joystick [/dev/input/jsX]
*
* See also:
* https://www.kernel.org/doc/Documentation/input/joystick-api.txt
*/
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <linux/joystick.h>
/**
* Reads a joystick event from the joystick device.
*
* Returns 0 on success. Otherwise -1 is returned.
*/
int read_event(int fd, struct js_event *event)
{
ssize_t bytes;
bytes = read(fd, event, sizeof(*event));
if (bytes == sizeof(*event))
return 0;
/* Error, could not read full event. */
return -1;
}
/**
* Returns the number of axes on the controller or 0 if an error occurs.
*/
size_t get_axis_count(int fd)
{
__u8 axes;
if (ioctl(fd, JSIOCGAXES, &axes) == -1)
return 0;
return axes;
}
/**
* Returns the number of buttons on the controller or 0 if an error occurs.
*/
size_t get_button_count(int fd)
{
__u8 buttons;
if (ioctl(fd, JSIOCGBUTTONS, &buttons) == -1)
return 0;
return buttons;
}
/**
* Current state of an axis.
*/
struct axis_state {
short x, y;
};
/**
* Keeps track of the current axis state.
*
* NOTE: This function assumes that axes are numbered starting from 0, and that
* the X axis is an even number, and the Y axis is an odd number. However, this
* is usually a safe assumption.
*
* Returns the axis that the event indicated.
*/
size_t get_axis_state(struct js_event *event, struct axis_state axes[3])
{
size_t axis = event->number / 2;
if (axis < 3)
{
if (event->number % 2 == 0)
axes[axis].x = event->value;
else
axes[axis].y = event->value;
}
return axis;
}
int main(int argc, char *argv[])
{
const char *device;
int js;
struct js_event event;
struct axis_state axes[3] = {0};
size_t axis;
if (argc > 1)
device = argv[1];
else
device = "/dev/input/js0";
js = open(device, O_RDONLY);
if (js == -1)
perror("Could not open joystick");
/* This loop will exit if the controller is unplugged. */
while (read_event(js, &event) == 0)
{
switch (event.type)
{
case JS_EVENT_BUTTON:
printf("Button %u %s\n", event.number, event.value ? "pressed" : "released");
break;
case JS_EVENT_AXIS:
axis = get_axis_state(&event, axes);
if (axis < 3)
printf("Axis %zu at (%6d, %6d)\n", axis, axes[axis].x, axes[axis].y);
break;
default:
/* Ignore init events. */
break;
}
fflush(stdout);
}
close(js);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment