Initial Commit
This commit is contained in:
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
6
CMakeLists.txt
Normal file
6
CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.30)
|
||||
project(jstick)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(jstick main.cpp)
|
6
jstick.hpp
Normal file
6
jstick.hpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
|
||||
void jstick_read_events();
|
212
main.cpp
Normal file
212
main.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* 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 <cstdio>
|
||||
#include <unistd.h>
|
||||
#include <linux/joystick.h>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
uint8_t get_num_axes(int joystick_handle) {
|
||||
char num_axes;
|
||||
ioctl(joystick_handle, JSIOCGAXES, &num_axes);
|
||||
return num_axes;
|
||||
}
|
||||
|
||||
std::string get_joystick_name(int joystick_handle)
|
||||
{
|
||||
char name_buf[128];
|
||||
if (ioctl(joystick_handle, JSIOCGNAME(sizeof(name_buf)), name_buf) < 0)
|
||||
strncpy(name_buf, "Unknown", sizeof(name_buf));
|
||||
return std::string(name_buf);
|
||||
}
|
||||
|
||||
int get_joystick_driver_ver(int joystick_handle)
|
||||
{
|
||||
int version;
|
||||
ioctl(joystick_handle, JSIOCGVERSION, &version);
|
||||
return version;
|
||||
}
|
||||
|
||||
bool check_for_joystick_device()
|
||||
{
|
||||
return std::filesystem::exists("/dev/input/js0");
|
||||
}
|
||||
|
||||
int js;
|
||||
bool device_open;
|
||||
|
||||
bool connect_device() {
|
||||
js = open("/dev/input/js0", O_NONBLOCK);
|
||||
|
||||
if (js == -1)
|
||||
perror("Could not open joystick");
|
||||
|
||||
|
||||
std::cout << get_joystick_name(js) << std::endl;
|
||||
std::cout << get_joystick_driver_ver(js) << std::endl;
|
||||
std::cout << get_axis_count(js) << std::endl;
|
||||
}
|
||||
|
||||
void disconnect_device() {
|
||||
close(js);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *device;
|
||||
|
||||
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_NONBLOCK);
|
||||
|
||||
if (js == -1)
|
||||
perror("Could not open joystick");
|
||||
|
||||
|
||||
std::cout << get_joystick_name(js) << std::endl;
|
||||
std::cout << get_joystick_driver_ver(js) << std::endl;
|
||||
std::cout << get_axis_count(js) << std::endl;
|
||||
|
||||
/// This loop will exit if the controller is unplugged.
|
||||
|
||||
bool had = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
bool has_file = check_for_joystick_device();
|
||||
|
||||
if (has_file && !had) {
|
||||
if (js == -1)
|
||||
{
|
||||
std::cout << "Controller plugged in!" << std::endl;
|
||||
js = open(device, O_NONBLOCK);
|
||||
|
||||
if (js == -1)
|
||||
perror("Could not open joystick");
|
||||
}
|
||||
|
||||
} else if (!has_file && had) {
|
||||
std::cout << "Controller unplugged!" << std::endl;
|
||||
if (js != -1) {
|
||||
close(js);
|
||||
js = -1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
had = has_file;
|
||||
|
||||
|
||||
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;
|
||||
case JS_EVENT_INIT:
|
||||
default:
|
||||
/// Ignore init events.
|
||||
break;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
close(js);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user