add initial gamecontroller (ujoy(4)) support to godot

Based on code used in sdl2 backend. Tested with XBox {360,One}
gamecontrollers.
Discussion, feedback, contributions, and encouragement op@ (maintainer)
also enable DEBUG_PACKAGES while here
ok op@
This commit is contained in:
thfr 2022-04-15 20:23:19 +00:00
parent 3fa798f918
commit 527fadb743
7 changed files with 660 additions and 9 deletions

View File

@ -6,6 +6,7 @@ V = 3.4.4
GODOTSTEAM_V = g34-s152-gs311
DISTNAME = godot-${V}-stable
PKGNAME = godot-${V}
REVISION = 0
CATEGORIES = games
HOMEPAGE = https://godotengine.org/
MAINTAINER = Omar Polo <op@omarpolo.com>
@ -17,7 +18,7 @@ WANTLIB += ${COMPILER_LIBCXX} BulletCollision BulletDynamics BulletSoftBody
WANTLIB += LinearMath GL X11 Xau Xcursor Xdmcp Xext Xfixes Xi Xinerama Xrandr
WANTLIB += Xrender c enet execinfo freetype intl m mbedtls mbedcrypto
WANTLIB += mbedx509 mpcdec ogg opus opusfile png sndio steam_api theora
WANTLIB += theoradec vorbis vorbisfile webp xcb z pcre2-32 vpx zstd
WANTLIB += theoradec usbhid vorbis vorbisfile webp xcb z pcre2-32 vpx zstd
# C++14
COMPILER = base-clang ports-gcc
@ -37,7 +38,7 @@ MODSCONS_FLAGS = CC="${CC}" \
CXX="${CXX}" \
CFLAGS="${CFLAGS}" \
CXXFLAGS="${CXXFLAGS} -Wno-deprecated-register" \
LINKFLAGS="${LDFLAGS} -lintl -lmpcdec" \
LINKFLAGS="${LDFLAGS} -lintl -lmpcdec -lusbhid" \
builtin_bullet=no \
builtin_enet=no \
builtin_freetype=no \
@ -84,6 +85,7 @@ LIB_DEPENDS = archivers/zstd \
security/polarssl
RUN_DEPENDS = devel/desktop-file-utils
DEBUG_PACKAGES = ${BUILD_PACKAGES}
NO_TEST = Yes
DPB_PROPERTIES = parallel
@ -96,7 +98,9 @@ WANTLIB += atomic
CFLAGS += -I${LOCALBASE}/include/goldberg_emulator
post-extract:
cp -R ${FILESDIR}/sndio ${WRKDIST}/drivers
cp -R ${FILESDIR}/sndio ${WRKDIST}/drivers
cp ${FILESDIR}/ujoy/joypad_openbsd.{cpp,h} \
${WRKDIST}/platform/x11/
pre-configure:
${SUBST_CMD} ${WRKSRC}/drivers/unix/os_unix.cpp

View File

@ -0,0 +1,479 @@
/*************************************************************************/
/* joypad_openbsd.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
//author: Thomas Frohwein <thfr@openbsd.org>
#ifdef JOYDEV_ENABLED
#include "joypad_openbsd.h"
#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
extern "C" {
#include <dev/usb/usb.h>
#include <dev/usb/usbhid.h>
#include <usbhid.h>
}
#define HUG_DPAD_UP 0x90
#define HUG_DPAD_DOWN 0x91
#define HUG_DPAD_RIGHT 0x92
#define HUG_DPAD_LEFT 0x93
#define HAT_CENTERED 0x00
#define HAT_UP 0x01
#define HAT_RIGHT 0x02
#define HAT_DOWN 0x04
#define HAT_LEFT 0x08
#define HAT_RIGHTUP (HAT_RIGHT|HAT_UP)
#define HAT_RIGHTDOWN (HAT_RIGHT|HAT_DOWN)
#define HAT_LEFTUP (HAT_LEFT|HAT_UP)
#define HAT_LEFTDOWN (HAT_LEFT|HAT_DOWN)
#define REP_BUF_DATA(rep) ((rep)->buf->ucr_data)
static struct
{
int uhid_report;
hid_kind_t kind;
const char *name;
} const repinfo[] = {
{UHID_INPUT_REPORT, hid_input, "input"},
{UHID_OUTPUT_REPORT, hid_output, "output"},
{UHID_FEATURE_REPORT, hid_feature, "feature"}
};
enum
{
REPORT_INPUT,
REPORT_OUTPUT,
REPORT_FEATURE
};
enum
{
JOYAXE_X,
JOYAXE_Y,
JOYAXE_Z,
JOYAXE_SLIDER,
JOYAXE_WHEEL,
JOYAXE_RX,
JOYAXE_RY,
JOYAXE_RZ,
JOYAXE_count
};
static int
report_alloc(struct report *r, struct report_desc *rd, int repind)
{
int len;
len = hid_report_size(rd, repinfo[repind].kind, r->rid);
if (len < 0) {
ERR_PRINT("Negative HID report siz");
return ERR_PARAMETER_RANGE_ERROR;
}
r->size = len;
if (r->size > 0) {
r->buf = (usb_ctl_report *)malloc(sizeof(*r->buf) - sizeof(REP_BUF_DATA(r)) + r->size);
if (r->buf == NULL)
return ERR_OUT_OF_MEMORY;
} else {
r->buf = NULL;
}
r->status = report::SREPORT_CLEAN;
return OK;
}
static int
usage_to_joyaxe(unsigned usage)
{
switch (usage) {
case HUG_X:
return JOYAXE_X;
case HUG_Y:
return JOYAXE_Y;
case HUG_Z:
return JOYAXE_Z;
case HUG_SLIDER:
return JOYAXE_SLIDER;
case HUG_WHEEL:
return JOYAXE_WHEEL;
case HUG_RX:
return JOYAXE_RX;
case HUG_RY:
return JOYAXE_RY;
case HUG_RZ:
return JOYAXE_RZ;
default:
return -1;
}
}
static unsigned
hatval_conversion(int hatval)
{
static const unsigned hat_dir_map[8] = {
HAT_UP, HAT_RIGHTUP, HAT_RIGHT, HAT_RIGHTDOWN,
HAT_DOWN, HAT_LEFTDOWN, HAT_LEFT, HAT_LEFTUP
};
if ((hatval & 7) == hatval)
return hat_dir_map[hatval];
else
return HAT_CENTERED;
}
/* calculate the value from the state of the dpad */
int
dpad_conversion(int *dpad)
{
if (dpad[2]) {
if (dpad[0])
return HAT_RIGHTUP;
else if (dpad[1])
return HAT_RIGHTDOWN;
else
return HAT_RIGHT;
} else if (dpad[3]) {
if (dpad[0])
return HAT_LEFTUP;
else if (dpad[1])
return HAT_LEFTDOWN;
else
return HAT_LEFT;
} else if (dpad[0]) {
return HAT_UP;
} else if (dpad[1]) {
return HAT_DOWN;
}
return HAT_CENTERED;
}
JoypadOpenBSD::Joypad::Joypad() {
fd = -1;
dpad = 0;
devpath = "";
}
JoypadOpenBSD::Joypad::~Joypad() {
}
void JoypadOpenBSD::Joypad::reset() {
dpad = 0;
fd = -1;
InputDefault::JoyAxis jx;
jx.min = -1;
jx.value = 0.0f;
}
JoypadOpenBSD::JoypadOpenBSD(InputDefault *in) {
input = in;
joy_thread.start(joy_thread_func, this);
hid_init(NULL);
}
JoypadOpenBSD::~JoypadOpenBSD() {
exit_monitor.set();
joy_thread.wait_to_finish();
close_joypad();
}
void JoypadOpenBSD::joy_thread_func(void *p_user) {
if (p_user) {
JoypadOpenBSD *joy = (JoypadOpenBSD *)p_user;
joy->run_joypad_thread();
}
}
void JoypadOpenBSD::run_joypad_thread() {
monitor_joypads();
}
void JoypadOpenBSD::monitor_joypads() {
while (!exit_monitor.is_set()) {
joy_mutex.lock();
for (int i = 0; i < 32; i++) {
char fname[64];
sprintf(fname, "/dev/ujoy/%d", i);
if (attached_devices.find(fname) == -1) {
open_joypad(fname);
}
}
joy_mutex.unlock();
usleep(1000000); // 1s
}
}
int JoypadOpenBSD::get_joy_from_path(String p_path) const {
for (int i = 0; i < JOYPADS_MAX; i++) {
if (joypads[i].devpath == p_path) {
return i;
}
}
return -2;
}
void JoypadOpenBSD::close_joypad(int p_id) {
if (p_id == -1) {
for (int i = 0; i < JOYPADS_MAX; i++) {
close_joypad(i);
};
return;
} else if (p_id < 0)
return;
Joypad &joy = joypads[p_id];
if (joy.fd != -1) {
close(joy.fd);
joy.fd = -1;
attached_devices.remove(attached_devices.find(joy.devpath));
input->joy_connection_changed(p_id, false, "");
};
}
void JoypadOpenBSD::setup_joypad_properties(int p_id) {
Error err;
Joypad *joy = &joypads[p_id];
struct hid_item hitem;
struct hid_data *hdata;
struct report *rep = NULL;
int i;
int ax;
for (ax = 0; ax < JOYAXE_count; ax++)
joy->axis_map[ax] = -1;
joy->type = Joypad::BSDJOY_UHID; // TODO: hardcoded; later check if /dev/joyX or /dev/ujoy/X
joy->repdesc = hid_get_report_desc(joy->fd);
if (joy->repdesc == NULL) {
ERR_PRINT("getting USB report descriptor");
}
rep = &joy->inreport;
if (ioctl(joy->fd, USB_GET_REPORT_ID, &rep->rid) < 0) {
rep->rid = -1; /* XXX */
}
err = (Error)report_alloc(rep, joy->repdesc, REPORT_INPUT);
if (err != OK) {
ERR_PRINT("allocating report descriptor");
}
if (rep->size <= 0) {
ERR_PRINT("input report descriptor has invalid length");
}
hdata = hid_start_parse(joy->repdesc, 1 << hid_input, rep->rid);
if (hdata == NULL) {
ERR_PRINT("cannot start HID parser");
}
int num_buttons = 0;
int num_axes = 0;
int num_hats = 0;
while (hid_get_item(hdata, &hitem)) {
switch (hitem.kind) {
case hid_input:
switch (HID_PAGE(hitem.usage)) {
case HUP_GENERIC_DESKTOP: {
unsigned usage = HID_USAGE(hitem.usage);
int joyaxe = usage_to_joyaxe(usage);
if (joyaxe >= 0) {
joy->axis_map[joyaxe] = 1;
} else if (usage == HUG_HAT_SWITCH || usage == HUG_DPAD_UP) {
num_hats++;
}
break;
}
case HUP_BUTTON:
num_buttons++;
break;
default:
break;
}
default:
break;
}
}
hid_end_parse(hdata);
for (i = 0; i < JOYAXE_count; i++)
if (joy->axis_map[i] > 0)
joy->axis_map[i] = num_axes++;
if (num_axes == 0 && num_buttons == 0 && num_hats == 0) {
ERR_PRINT("Not a joystick!");
} else {
printf("joypad %d: %d axes %d buttons %d hats\n", p_id, num_axes, num_buttons, num_hats);
}
joy->force_feedback = false;
joy->ff_effect_timestamp = 0;
}
void JoypadOpenBSD::open_joypad(const char *p_path) {
int joy_num = input->get_unused_joy_id();
if (joy_num < 0) {
ERR_PRINT("no ID available to assign to joypad device");
return;
}
int fd = open(p_path, O_RDONLY | O_NONBLOCK);
if (fd != -1 && joy_num != -1) {
// add to attached devices so we don't try to open it again
attached_devices.push_back(String(p_path));
String name = "";
joypads[joy_num].reset();
Joypad &joy = joypads[joy_num];
joy.fd = fd;
joy.devpath = String(p_path);
setup_joypad_properties(joy_num);
String uidname = "00";
input->joy_connection_changed(joy_num, true, name, uidname);
}
}
void JoypadOpenBSD::joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp) {
/* not supported */
}
void JoypadOpenBSD::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
/* not supported */
}
InputDefault::JoyAxis JoypadOpenBSD::axis_correct(int min, int max, int p_value) const {
InputDefault::JoyAxis jx;
if (min < 0) {
jx.min = -1;
if (p_value < 0) {
jx.value = (float)-p_value / min;
} else {
jx.value = (float)p_value / max;
}
} else if (min == 0) {
jx.min = 0;
jx.value = 0.0f + (float)p_value / max;
}
return jx;
}
void JoypadOpenBSD::process_joypads() {
struct hid_item hitem;
struct hid_data *hdata;
struct report *rep;
int nbutton, naxe = -1;
int v;
int dpad[4] = { 0, 0, 0, 0 };
int actualbutton;
if (joy_mutex.try_lock() != OK) {
return;
}
for (int i = 0; i < JOYPADS_MAX; i++) {
if (joypads[i].fd == -1) continue;
Joypad *joy = &joypads[i];
rep = &joy->inreport;
while (true) {
ssize_t r = read(joy->fd, REP_BUF_DATA(rep), rep->size);
if (r < 0 || (size_t)r != rep->size) {
break;
}
hdata = hid_start_parse(joy->repdesc, 1 << hid_input, rep->rid);
if (hdata == NULL) {
continue;
}
for (nbutton = 0; hid_get_item(hdata, &hitem) > 0;) {
switch (hitem.kind) {
case hid_input:
unsigned usage;
int joyaxe;
switch (HID_PAGE(hitem.usage)) {
case HUP_GENERIC_DESKTOP:
usage = HID_USAGE(hitem.usage);
joyaxe = usage_to_joyaxe(usage);
if (joyaxe >= 0) {
naxe = joy->axis_map[joyaxe];
v = hid_get_data(REP_BUF_DATA(rep), &hitem);
/* XInput controllermapping relies on inverted Y axes.
* These devices have a 16bit signed space, as opposed
* to older DInput devices (8bit unsigned), so
* hitem.logical_maximum can be used to differentiate them.
*/
if ((joyaxe == JOYAXE_Y || joyaxe == JOYAXE_RY)
&& hitem.logical_maximum > 255) {
if (v != 0)
v = ~v;
}
input->joy_axis(i, joyaxe, axis_correct(hitem.logical_minimum, hitem.logical_maximum, v));
break;
} else if (usage == HUG_HAT_SWITCH) {
v = hid_get_data(REP_BUF_DATA(rep), &hitem);
joy->dpad = hatval_conversion(v);
} else if (usage == HUG_DPAD_UP) {
dpad[0] = hid_get_data(REP_BUF_DATA(rep), &hitem);
joy->dpad = dpad_conversion(dpad);
} else if (usage == HUG_DPAD_DOWN) {
dpad[1] = hid_get_data(REP_BUF_DATA(rep), &hitem);
joy->dpad = dpad_conversion(dpad);
} else if (usage == HUG_DPAD_RIGHT) {
dpad[2] = hid_get_data(REP_BUF_DATA(rep), &hitem);
joy->dpad = dpad_conversion(dpad);
} else if (usage == HUG_DPAD_LEFT) {
dpad[3] = hid_get_data(REP_BUF_DATA(rep), &hitem);
joy->dpad = dpad_conversion(dpad);
}
input->joy_hat(i, joy->dpad);
break;
case HUP_BUTTON:
v = hid_get_data(REP_BUF_DATA(rep), &hitem);
actualbutton = HID_USAGE(hitem.usage) - 1; // buttons are zero-based
input->joy_button(i, actualbutton, v);
default:
continue;
}
break;
default:
break;
}
}
hid_end_parse(hdata);
}
}
joy_mutex.unlock();
}
#endif

View File

@ -0,0 +1,121 @@
/*************************************************************************/
/* joypad_openbsd.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
//author: Thomas Frohwein <thfr@openbsd.org>
#ifndef JOYPAD_OPENBSD_H
#define JOYPAD_OPENBSD_H
#ifdef JOYDEV_ENABLED
#include "core/os/mutex.h"
#include "core/os/thread.h"
#include "main/input_default.h"
struct input_absinfo;
struct report
{
struct usb_ctl_report *buf; /* Buffer */
size_t size; /* Buffer size */
int rid; /* Report ID */
enum
{
SREPORT_UNINIT,
SREPORT_CLEAN,
SREPORT_DIRTY
} status;
};
class JoypadOpenBSD {
public:
JoypadOpenBSD(InputDefault *in);
~JoypadOpenBSD();
void process_joypads();
private:
enum {
JOYPADS_MAX = 16,
MAX_ABS = 63,
MAX_KEY = 767, // Hack because <linux/input.h> can't be included here
};
struct Joypad {
InputDefault::JoyAxis curr_axis[MAX_ABS];
int key_map[MAX_KEY];
int abs_map[MAX_ABS];
int dpad;
int fd;
char *path;
enum
{
BSDJOY_UHID, /* uhid(4) */
BSDJOY_JOY /* joy(4) */
} type;
struct report_desc *repdesc;
struct report inreport;
int axis_map[8]; /* TODO: replace with JOYAXE_count */
String devpath;
input_absinfo *abs_info[MAX_ABS];
bool force_feedback;
int ff_effect_id;
uint64_t ff_effect_timestamp;
Joypad();
~Joypad();
void reset();
};
SafeFlag exit_monitor;
Mutex joy_mutex;
Thread joy_thread;
InputDefault *input;
Joypad joypads[JOYPADS_MAX];
Vector<String> attached_devices;
static void joy_thread_func(void *p_user);
int get_joy_from_path(String p_path) const;
void setup_joypad_properties(int p_id);
void close_joypad(int p_id = -1);
void monitor_joypads();
void run_joypad_thread();
void open_joypad(const char *p_path);
void joypad_vibration_start(int p_id, float p_weak_magnitude, float p_strong_magnitude, float p_duration, uint64_t p_timestamp);
void joypad_vibration_stop(int p_id, uint64_t p_timestamp);
InputDefault::JoyAxis axis_correct(int min, int max, int p_value) const;
};
#endif
#endif // JOYPAD_OPENBSD_H

View File

@ -0,0 +1,12 @@
Index: platform/x11/SCsub
--- platform/x11/SCsub.orig
+++ platform/x11/SCsub
@@ -10,7 +10,7 @@ common_x11 = [
"crash_handler_x11.cpp",
"os_x11.cpp",
"key_mapping_x11.cpp",
- "joypad_linux.cpp",
+ "joypad_openbsd.cpp",
"power_x11.cpp",
"detect_prime.cpp",
]

View File

@ -1,4 +1,5 @@
remove hardcoded -O2, found by bcallah@. Add sndio
enable joydev
Index: platform/x11/detect.py
--- platform/x11/detect.py.orig
@ -33,14 +34,24 @@ Index: platform/x11/detect.py
## Architecture
is64 = sys.maxsize > 2 ** 32
@@ -330,6 +307,10 @@ def configure(env):
env.Append(CPPDEFINES=["ALSA_ENABLED", "ALSAMIDI_ENABLED"])
@@ -331,6 +308,10 @@ def configure(env):
else:
print("Warning: ALSA libraries not found. Disabling the ALSA audio driver.")
+
+ print("Enabling sndio")
+ env.Append(CPPDEFINES=["SNDIO_ENABLED"])
+ env.Append(LINKFLAGS=["-lsndio"])
+
if env["pulseaudio"]:
if os.system("pkg-config --exists libpulse") == 0: # 0 means found
env.Append(CPPDEFINES=["PULSEAUDIO_ENABLED"])
@@ -347,6 +328,9 @@ def configure(env):
print("Warning: libudev development libraries not found. Disabling controller hotplugging support.")
else:
env["udev"] = False # Linux specific
+
+ if platform.system() == "OpenBSD":
+ env.Append(CPPDEFINES=["JOYDEV_ENABLED"])
# Linkflags below this line should typically stay the last ones
if not env["builtin_zlib"]:

View File

@ -1,4 +1,5 @@
fix libXrandr library name and load sndio
use OpenBSD joypad class
Index: platform/x11/os_x11.cpp
--- platform/x11/os_x11.cpp.orig
@ -12,6 +13,15 @@ Index: platform/x11/os_x11.cpp
if (!xrandr_handle) {
err = dlerror();
// For some arcane reason, NetBSD now ships libXrandr.so.3 while the rest of the world has libXrandr.so.2...
@@ -594,7 +594,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, i
window_has_focus = true; // Set focus to true at init
#ifdef JOYDEV_ENABLED
- joypad = memnew(JoypadLinux(input));
+ joypad = memnew(JoypadOpenBSD(input));
#endif
power_manager = memnew(PowerX11);
@@ -4056,6 +4056,11 @@ void OS_X11::update_real_mouse_position() {
}

View File

@ -1,16 +1,30 @@
load sndio
use OpenBSD joypad class
Index: platform/x11/os_x11.h
--- platform/x11/os_x11.h.orig
+++ platform/x11/os_x11.h
@@ -37,6 +37,7 @@
@@ -37,9 +37,10 @@
#include "crash_handler_x11.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/alsamidi/midi_driver_alsamidi.h"
+#include "drivers/sndio/audio_driver_sndio.h"
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
#include "drivers/unix/os_unix.h"
#include "joypad_linux.h"
-#include "joypad_linux.h"
+#include "joypad_openbsd.h"
#include "main/input_default.h"
#include "power_x11.h"
#include "servers/audio_server.h"
@@ -197,7 +198,7 @@ class OS_X11 : public OS_Unix {
InputDefault *input;
#ifdef JOYDEV_ENABLED
- JoypadLinux *joypad;
+ JoypadOpenBSD *joypad;
#endif
#ifdef ALSA_ENABLED
@@ -206,6 +207,10 @@ class OS_X11 : public OS_Unix {
#ifdef ALSAMIDI_ENABLED