Compare commits

..

No commits in common. "c84a30d4dd054741e5171af2c1aadf28bcd88e31" and "a5318448f51882cde44e7035fe123d6218bd5f8e" have entirely different histories.

6 changed files with 121 additions and 405 deletions

View File

@ -12,12 +12,6 @@ namespace Kernel
BAN_NON_COPYABLE(USBJoystick);
BAN_NON_MOVABLE(USBJoystick);
enum class Type
{
Unknown,
DualShock3,
};
public:
BAN::ErrorOr<void> initialize() override;
@ -28,42 +22,20 @@ namespace Kernel
void handle_variable(uint16_t usage_page, uint16_t usage, int64_t state) override;
void handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max) override;
void update() override;
protected:
BAN::ErrorOr<size_t> read_impl(off_t, BAN::ByteSpan) override;
bool can_read_impl() const override { return true; }
BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
private:
USBJoystick(USBHIDDriver&);
~USBJoystick() = default;
private:
void initialize_type();
BAN::ErrorOr<void> update_dualshock3_state(uint8_t led_bitmap, uint8_t rumble_strength);
private:
USBHIDDriver& m_driver;
Type m_type { Type::Unknown };
BAN::UniqPtr<DMARegion> m_send_buffer;
SpinLock m_state_lock;
InterruptState m_interrupt_state;
LibInput::JoystickState m_state;
size_t m_state_index { 0 };
BAN::Atomic<bool> m_has_got_report { false };
Mutex m_command_mutex;
BAN::Atomic<bool> m_has_initialized_leds { false };
uint8_t m_led_state { 0b0001 };
uint8_t m_rumble_strength { 0x00 };
LibInput::JoystickState m_state {};
friend class BAN::RefPtr<USBJoystick>;
};

View File

@ -1,9 +1,6 @@
#include <kernel/Input/InputDevice.h>
#include <kernel/Lock/LockGuard.h>
#include <kernel/USB/HID/Joystick.h>
#include <sys/ioctl.h>
namespace Kernel
{
@ -11,64 +8,35 @@ namespace Kernel
: USBHIDDevice(InputDevice::Type::Joystick)
, m_driver(driver)
{
using namespace LibInput;
m_state.axis[JSA_TRIGGER_LEFT] = -32767;
m_state.axis[JSA_TRIGGER_RIGHT] = -32767;
}
void USBJoystick::initialize_type()
{
m_type = Type::Unknown;
const auto& device_descriptor = m_driver.device().device_descriptor();
switch (device_descriptor.idVendor)
{
case 0x054C: // Sony
switch (device_descriptor.idProduct)
{
case 0x0268: // DualShock 3
m_type = Type::DualShock3;
break;
}
break;
}
}
BAN::ErrorOr<void> USBJoystick::initialize()
{
initialize_type();
// TODO: this is not a generic USB HID joystick driver but one for PS3 controller.
// this may still work with other HID joysticks so i won't limit this only
// based on the device.
m_send_buffer = TRY(DMARegion::create(PAGE_SIZE));
// linux hid-sony.c
auto temp_region = TRY(DMARegion::create(17));
USBDeviceRequest request;
switch (m_type)
{
case Type::Unknown:
break;
case Type::DualShock3:
{
// linux hid-sony.c
// move ps3 controller to "operational" state
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x01;
request.wValue = 0x03F2;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = 17;
TRY(m_driver.device().send_request(request, m_send_buffer->paddr()));
TRY(m_driver.device().send_request(request, temp_region->paddr()));
// some compatible controllers need this too (we don't detect compatible controllers though)
// some compatible controllers need this too
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x01;
request.wValue = 0x03F5;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = 8;
TRY(m_driver.device().send_request(request, m_send_buffer->paddr()));
break;
}
}
TRY(m_driver.device().send_request(request, temp_region->paddr()));
return {};
}
@ -76,13 +44,16 @@ namespace Kernel
void USBJoystick::start_report()
{
m_interrupt_state = m_state_lock.lock();
m_state_index = 0;
for (auto& axis : m_state.axis)
axis = {};
for (auto& button : m_state.buttons)
button = false;
}
void USBJoystick::stop_report()
{
m_state_lock.unlock(m_interrupt_state);
m_has_got_report = true;
}
void USBJoystick::handle_array(uint16_t usage_page, uint16_t usage)
@ -100,76 +71,31 @@ namespace Kernel
void USBJoystick::handle_variable_absolute(uint16_t usage_page, uint16_t usage, int64_t state, int64_t min, int64_t max)
{
using namespace LibInput;
constexpr auto map_joystick_axis =
[](int64_t value, int64_t min, int64_t max) -> int16_t
{
if (min == max)
return 0;
return (value - min) * 65534 / (max - min) - 32767;
};
constexpr auto map_trigger_axis =
[](int64_t value, int64_t min, int64_t max) -> int16_t
{
if (min == max)
return -32767;
return (value - min) * 65534 / (max - min) - 32767;
};
static constexpr JoystickButton button_map[] {
[ 0] = JSB_SELECT,
[ 1] = JSB_STICK_LEFT,
[ 2] = JSB_STICK_RIGHT,
[ 3] = JSB_START,
[ 4] = JSB_DPAD_UP,
[ 5] = JSB_DPAD_RIGHT,
[ 6] = JSB_DPAD_DOWN,
[ 7] = JSB_DPAD_LEFT,
[ 8] = JSB_COUNT, // left trigger
[ 9] = JSB_COUNT, // right trigger
[10] = JSB_SHOULDER_LEFT,
[11] = JSB_SHOULDER_RIGHT,
[12] = JSB_FACE_UP,
[13] = JSB_FACE_RIGHT,
[14] = JSB_FACE_DOWN,
[15] = JSB_FACE_LEFT,
[16] = JSB_MENU,
};
switch (usage_page)
{
case 0x01:
// TODO: These are probably only correct for dualshock 3
switch (usage)
{
case 0x01:
if (m_state_index == 8)
m_state.axis[JSA_TRIGGER_LEFT] = map_trigger_axis(state, min, max);
if (m_state_index == 9)
m_state.axis[JSA_TRIGGER_RIGHT] = map_trigger_axis(state, min, max);
m_state_index++;
// TODO: PS3 controller sends some extra data with this usage
break;
case 0x30:
m_state.axis[JSA_STICK_LEFT_X] = map_joystick_axis(state, min, max);
m_state.axis[0] = { state, min, max };
break;
case 0x31:
m_state.axis[JSA_STICK_LEFT_Y] = map_joystick_axis(state, min, max);
m_state.axis[1] = { state, min, max };
break;
case 0x32:
m_state.axis[JSA_STICK_RIGHT_X] = map_joystick_axis(state, min, max);
m_state.axis[2] = { state, min, max };
break;
case 0x35:
m_state.axis[JSA_STICK_RIGHT_Y] = map_joystick_axis(state, min, max);
m_state.axis[3] = { state, min, max };
break;
}
break;
case 0x09:
// TODO: These are probably only correct for dualshock 3
if (usage > 0 && usage <= sizeof(button_map) / sizeof(*button_map))
if (const auto button = button_map[usage - 1]; button != JSB_COUNT)
m_state.buttons[button] = state;
if (usage > 0 && usage <= sizeof(m_state.buttons))
m_state.buttons[usage - 1] = state;
break;
default:
dprintln("Unsupported absolute usage page {2H}", usage_page);
@ -185,112 +111,4 @@ namespace Kernel
return to_copy;
}
BAN::ErrorOr<long> USBJoystick::ioctl_impl(int request, void* arg)
{
switch (request)
{
case JOYSTICK_GET_LEDS:
*static_cast<uint8_t*>(arg) = m_led_state;
return 0;
case JOYSTICK_SET_LEDS:
switch (m_type)
{
case Type::Unknown:
return BAN::Error::from_errno(ENOTSUP);
case Type::DualShock3:
TRY(update_dualshock3_state(*static_cast<const uint8_t*>(arg), m_rumble_strength));
return 0;
}
ASSERT_NOT_REACHED();
case JOYSTICK_GET_RUMBLE:
*static_cast<uint32_t*>(arg) = m_rumble_strength;
return 0;
case JOYSTICK_SET_RUMBLE:
switch (m_type)
{
case Type::Unknown:
return BAN::Error::from_errno(ENOTSUP);
case Type::DualShock3:
TRY(update_dualshock3_state(m_led_state, *static_cast<const uint32_t*>(arg)));
return 0;
}
ASSERT_NOT_REACHED();
}
return USBHIDDevice::ioctl(request, arg);
}
void USBJoystick::update()
{
if (!m_has_got_report)
return;
switch (m_type)
{
case Type::Unknown:
break;
case Type::DualShock3:
// DualShock 3 only accepts leds after it has started sending reports
// (when you press the PS button)
if (!m_has_initialized_leds)
(void)update_dualshock3_state(m_led_state, m_rumble_strength);
break;
}
}
BAN::ErrorOr<void> USBJoystick::update_dualshock3_state(uint8_t led_state, uint8_t rumble_strength)
{
led_state &= 0x0F;
LockGuard _(m_command_mutex);
// we cannot do anything until we have received an reports
if (!m_has_got_report)
{
m_led_state = led_state;
m_rumble_strength = rumble_strength;
return {};
}
auto* request_data = reinterpret_cast<uint8_t*>(m_send_buffer->vaddr());
memset(request_data, 0, 35);
// header
request_data[0] = 0x01; // report id (?)
request_data[1] = 0xFF; // no idea but linux sets this, doesn't seem to affect anything
// first byte is maybe *enable rumble control*, it has to be non-zero for rumble to do anything
request_data[3] = 0xFF;
request_data[4] = rumble_strength;
// LED bitmap (bit 1: led 1, bit 2: led 2, ...)
request_data[9] = led_state << 1;
// No idea what these do but they need to be correct for the corresponding led to turn on.
// Also they are in reverse order, first entry corresponds to led 4, second to led 3, ...
for (size_t i = 0; i < 4; i++)
{
// values are the same as linux sends
request_data[10 + i * 5] = 0xFF; // has to be non zero
request_data[11 + i * 5] = 0x27; // ignored
request_data[12 + i * 5] = 0x10; // has to be non zero
request_data[13 + i * 5] = 0x00; // ignored
request_data[14 + i * 5] = 0x32; // has to be non zero
}
USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = 0x09;
request.wValue = 0x0201;
request.wIndex = m_driver.interface().descriptor.bInterfaceNumber;
request.wLength = 35;
TRY(m_driver.device().send_request(request, m_send_buffer->paddr()));
m_led_state = led_state;
m_rumble_strength = rumble_strength;
m_has_initialized_leds = true;
return {};
}
}

View File

@ -1,6 +1,6 @@
diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake
--- SDL2-2.32.8/cmake/sdlplatform.cmake 2024-08-14 13:35:43.000000000 +0300
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2026-01-07 19:04:34.332166371 +0200
+++ SDL2-2.32.8-banan_os/cmake/sdlplatform.cmake 2026-01-03 19:50:45.777185459 +0200
@@ -28,6 +28,8 @@
set(SDL_CMAKE_PLATFORM AIX)
elseif(CMAKE_SYSTEM_NAME MATCHES "Minix.*")
@ -12,7 +12,7 @@ diff -ruN SDL2-2.32.8/cmake/sdlplatform.cmake SDL2-2.32.8-banan_os/cmake/sdlplat
endif()
diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
--- SDL2-2.32.8/CMakeLists.txt 2025-06-03 02:00:39.000000000 +0300
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2026-01-07 19:04:34.343116295 +0200
+++ SDL2-2.32.8-banan_os/CMakeLists.txt 2026-01-03 19:51:02.494165302 +0200
@@ -14,7 +14,7 @@
set(SDL2_SUBPROJECT ON)
endif()
@ -98,7 +98,7 @@ diff -ruN SDL2-2.32.8/CMakeLists.txt SDL2-2.32.8-banan_os/CMakeLists.txt
file(GLOB MISC_SOURCES ${SDL2_SOURCE_DIR}/src/misc/riscos/*.c)
diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SDL_config.h.cmake
--- SDL2-2.32.8/include/SDL_config.h.cmake 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2026-01-07 19:04:34.358682129 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_config.h.cmake 2026-01-03 19:55:22.679890924 +0200
@@ -307,6 +307,7 @@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND @SDL_AUDIO_DRIVER_FUSIONSOUND@
#cmakedefine SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC @SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC@
@ -125,7 +125,7 @@ diff -ruN SDL2-2.32.8/include/SDL_config.h.cmake SDL2-2.32.8-banan_os/include/SD
#cmakedefine SDL_VIDEO_DRIVER_DIRECTFB @SDL_VIDEO_DRIVER_DIRECTFB@
diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_platform.h
--- SDL2-2.32.8/include/SDL_platform.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2026-01-07 19:04:34.370086235 +0200
+++ SDL2-2.32.8-banan_os/include/SDL_platform.h 2026-01-03 19:50:45.778818009 +0200
@@ -36,6 +36,10 @@
#undef __HAIKU__
#define __HAIKU__ 1
@ -139,7 +139,7 @@ diff -ruN SDL2-2.32.8/include/SDL_platform.h SDL2-2.32.8-banan_os/include/SDL_pl
#define __BSDI__ 1
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2026-01-07 19:04:34.370691623 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.cpp 2026-01-03 19:50:45.779146754 +0200
@@ -0,0 +1,150 @@
+/*
+ Simple DirectMedia Layer
@ -293,7 +293,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.cpp SDL2-2.32.8-bana
+#endif
diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h
--- SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2026-01-07 19:04:34.370883199 +0200
+++ SDL2-2.32.8-banan_os/src/audio/banan_os/SDL_banan_os_audio.h 2026-01-03 19:50:45.779253053 +0200
@@ -0,0 +1,34 @@
+/*
+ Simple DirectMedia Layer
@ -331,7 +331,7 @@ diff -ruN SDL2-2.32.8/src/audio/banan_os/SDL_banan_os_audio.h SDL2-2.32.8-banan_
+};
diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_audio.c
--- SDL2-2.32.8/src/audio/SDL_audio.c 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2026-01-07 19:04:34.371410923 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_audio.c 2026-01-03 19:50:45.779381073 +0200
@@ -87,6 +87,9 @@
#ifdef SDL_AUDIO_DRIVER_HAIKU
&HAIKUAUDIO_bootstrap,
@ -344,7 +344,7 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_audio.c SDL2-2.32.8-banan_os/src/audio/SDL_a
#endif
diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h
--- SDL2-2.32.8/src/audio/SDL_sysaudio.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2026-01-07 19:04:34.372150756 +0200
+++ SDL2-2.32.8-banan_os/src/audio/SDL_sysaudio.h 2026-01-03 19:50:45.779975705 +0200
@@ -196,6 +196,7 @@
extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap;
@ -355,8 +355,8 @@ diff -ruN SDL2-2.32.8/src/audio/SDL_sysaudio.h SDL2-2.32.8-banan_os/src/audio/SD
extern AudioBootStrap DUMMYAUDIO_bootstrap;
diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.8-banan_os/src/joystick/banan_os/SDL_banan_os_joystick.cpp
--- SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/banan_os/SDL_banan_os_joystick.cpp 2026-01-07 19:07:12.677617077 +0200
@@ -0,0 +1,296 @@
+++ SDL2-2.32.8-banan_os/src/joystick/banan_os/SDL_banan_os_joystick.cpp 2026-01-03 19:51:21.437329388 +0200
@@ -0,0 +1,308 @@
+/*
+Simple DirectMedia Layer
+Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
@ -408,6 +408,8 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+static int s_joystick_count = 0;
+static char* s_joystick_path[MAX_JOYSTICKS];
+
+static void BANANOS_JoystickDetect(void);
+
+static int BANANOS_JoystickInit(void)
+{
+ s_joystick_count = 0;
@ -496,8 +498,8 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+ return SDL_SetError("Unable to open joystick");
+ }
+
+ joystick->nbuttons = LibInput::JSB_COUNT;
+ joystick->naxes = LibInput::JSA_COUNT;
+ joystick->nbuttons = sizeof(LibInput::JoystickState::buttons) / sizeof(*LibInput::JoystickState::buttons);
+ joystick->naxes = sizeof(LibInput::JoystickState::axis) / sizeof(*LibInput::JoystickState::axis);
+ joystick->nhats = 0;
+
+ return 0;
@ -509,8 +511,17 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+ if (read(joystick->hwdata->fd, &state, sizeof(state)) < static_cast<ssize_t>(sizeof(state)))
+ return;
+
+ const auto map_joystick_value =
+ [](const LibInput::JoystickState::Axis& axis) -> Sint16
+ {
+ if (axis.min == axis.max)
+ return 0;
+ const float mapped = (axis.value - axis.min) * 65534.0f / (axis.max - axis.min) - 32767.0f;
+ return BAN::Math::clamp<Sint32>(mapped, -32767, 32767);
+ };
+
+ for (int i = 0; i < joystick->naxes; i++)
+ SDL_PrivateJoystickAxis(joystick, i, state.axis[i]);
+ SDL_PrivateJoystickAxis(joystick, i, map_joystick_value(state.axis[i]));
+
+ for (int i = 0; i < joystick->nbuttons; i++)
+ SDL_PrivateJoystickButton(joystick, i, state.buttons[i]);
@ -545,10 +556,10 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+
+static SDL_bool BANANOS_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping* out)
+{
+ using namespace LibInput;
+
+ (void)device_index;
+
+ // FIXME: this is hardcoded to a PS3 controller layout :D
+
+ memset(out, 0, sizeof(SDL_GamepadMapping));
+
+#define BANANOS_MAP_BUTTON(name, button) \
@ -559,33 +570,34 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+ out->name.kind = EMappingKind_Axis; \
+ out->name.target = axis
+
+ BANANOS_MAP_BUTTON(a, JSB_FACE_DOWN);
+ BANANOS_MAP_BUTTON(b, JSB_FACE_RIGHT);
+ BANANOS_MAP_BUTTON(x, JSB_FACE_LEFT);
+ BANANOS_MAP_BUTTON(y, JSB_FACE_UP);
+ BANANOS_MAP_BUTTON(a, 14);
+ BANANOS_MAP_BUTTON(b, 13);
+ BANANOS_MAP_BUTTON(x, 15);
+ BANANOS_MAP_BUTTON(y, 12);
+
+ BANANOS_MAP_BUTTON(back, JSB_SELECT);
+ BANANOS_MAP_BUTTON(guide, JSB_MENU);
+ BANANOS_MAP_BUTTON(start, JSB_START);
+ BANANOS_MAP_BUTTON(back, 0);
+ BANANOS_MAP_BUTTON(guide, 16);
+ BANANOS_MAP_BUTTON(start, 3);
+
+ BANANOS_MAP_BUTTON(leftstick, JSB_STICK_LEFT);
+ BANANOS_MAP_BUTTON(rightstick, JSB_STICK_RIGHT);
+ BANANOS_MAP_BUTTON(leftstick, 1);
+ BANANOS_MAP_BUTTON(rightstick, 2);
+
+ BANANOS_MAP_BUTTON(leftshoulder, JSB_SHOULDER_LEFT);
+ BANANOS_MAP_BUTTON(rightshoulder, JSB_SHOULDER_RIGHT);
+ BANANOS_MAP_BUTTON(leftshoulder, 10);
+ BANANOS_MAP_BUTTON(rightshoulder, 11);
+
+ BANANOS_MAP_BUTTON(dpup, JSB_DPAD_UP);
+ BANANOS_MAP_BUTTON(dpdown, JSB_DPAD_DOWN);
+ BANANOS_MAP_BUTTON(dpleft, JSB_DPAD_LEFT);
+ BANANOS_MAP_BUTTON(dpright, JSB_DPAD_RIGHT);
+ BANANOS_MAP_BUTTON(dpup, 4);
+ BANANOS_MAP_BUTTON(dpdown, 6);
+ BANANOS_MAP_BUTTON(dpleft, 7);
+ BANANOS_MAP_BUTTON(dpright, 5);
+
+ BANANOS_MAP_AXIS(leftx, JSA_STICK_LEFT_X);
+ BANANOS_MAP_AXIS(lefty, JSA_STICK_LEFT_Y);
+ BANANOS_MAP_AXIS(rightx, JSA_STICK_RIGHT_X);
+ BANANOS_MAP_AXIS(righty, JSA_STICK_RIGHT_Y);
+ BANANOS_MAP_AXIS(leftx, 0);
+ BANANOS_MAP_AXIS(lefty, 1);
+ BANANOS_MAP_AXIS(rightx, 2);
+ BANANOS_MAP_AXIS(righty, 3);
+
+ BANANOS_MAP_AXIS(lefttrigger, JSA_TRIGGER_LEFT);
+ BANANOS_MAP_AXIS(righttrigger, JSA_TRIGGER_RIGHT);
+ // TODO: these should probably be axis
+ BANANOS_MAP_BUTTON(lefttrigger, 8);
+ BANANOS_MAP_BUTTON(righttrigger, 9);
+
+#undef BANANOS_MAP_BUTTON
+#undef BANANOS_MAP_AXIS
@ -655,7 +667,7 @@ diff -ruN SDL2-2.32.8/src/joystick/banan_os/SDL_banan_os_joystick.cpp SDL2-2.32.
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/joystick/SDL_joystick.c SDL2-2.32.8-banan_os/src/joystick/SDL_joystick.c
--- SDL2-2.32.8/src/joystick/SDL_joystick.c 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_joystick.c 2026-01-07 19:04:34.373890653 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_joystick.c 2026-01-03 19:52:38.740921854 +0200
@@ -85,6 +85,9 @@
#ifdef SDL_JOYSTICK_HAIKU
&SDL_HAIKU_JoystickDriver,
@ -668,7 +680,7 @@ diff -ruN SDL2-2.32.8/src/joystick/SDL_joystick.c SDL2-2.32.8-banan_os/src/joyst
#endif
diff -ruN SDL2-2.32.8/src/joystick/SDL_sysjoystick.h SDL2-2.32.8-banan_os/src/joystick/SDL_sysjoystick.h
--- SDL2-2.32.8/src/joystick/SDL_sysjoystick.h 2025-01-01 17:47:53.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_sysjoystick.h 2026-01-07 19:04:34.374337431 +0200
+++ SDL2-2.32.8-banan_os/src/joystick/SDL_sysjoystick.h 2026-01-03 19:52:50.906765671 +0200
@@ -235,6 +235,7 @@
/* The available joystick drivers */
@ -679,7 +691,7 @@ diff -ruN SDL2-2.32.8/src/joystick/SDL_sysjoystick.h SDL2-2.32.8-banan_os/src/jo
extern SDL_JoystickDriver SDL_DUMMY_JoystickDriver;
diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp
--- SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2026-01-07 19:04:34.379748697 +0200
+++ SDL2-2.32.8-banan_os/src/misc/banan_os/SDL_sysurl.cpp 2026-01-03 19:50:45.780251300 +0200
@@ -0,0 +1,30 @@
+/*
+ Simple DirectMedia Layer
@ -713,7 +725,7 @@ diff -ruN SDL2-2.32.8/src/misc/banan_os/SDL_sysurl.cpp SDL2-2.32.8-banan_os/src/
+
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp 2026-01-07 19:04:34.379995308 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.cpp 2026-01-03 19:50:45.780447206 +0200
@@ -0,0 +1,51 @@
+/*
+ Simple DirectMedia Layer
@ -768,7 +780,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.cpp SDL2-2.32.8-
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h 2026-01-07 19:04:34.380137576 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_clipboard.h 2026-01-03 19:50:45.780567334 +0200
@@ -0,0 +1,43 @@
+/*
+ Simple DirectMedia Layer
@ -815,7 +827,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_clipboard.h SDL2-2.32.8-ba
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2026-01-07 19:04:34.380308339 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.cpp 2026-01-03 19:50:45.780690325 +0200
@@ -0,0 +1,60 @@
+/*
+ Simple DirectMedia Layer
@ -879,7 +891,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.cpp SDL2-2.32.
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2026-01-07 19:04:34.380550899 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_message_box.h 2026-01-03 19:50:45.780815551 +0200
@@ -0,0 +1,45 @@
+/*
+ Simple DirectMedia Layer
@ -928,7 +940,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_message_box.h SDL2-2.32.8-
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp
--- SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp 1970-01-01 02:00:00.000000000 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2026-01-07 19:04:34.380720824 +0200
+++ SDL2-2.32.8-banan_os/src/video/banan_os/SDL_banan_os_video.cpp 2026-01-03 19:50:45.780934771 +0200
@@ -0,0 +1,729 @@
+/*
+ Simple DirectMedia Layer
@ -1661,7 +1673,7 @@ diff -ruN SDL2-2.32.8/src/video/banan_os/SDL_banan_os_video.cpp SDL2-2.32.8-bana
+/* vi: set ts=4 sw=4 expandtab: */
diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h
--- SDL2-2.32.8/src/video/SDL_sysvideo.h 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2026-01-07 19:04:34.381316574 +0200
+++ SDL2-2.32.8-banan_os/src/video/SDL_sysvideo.h 2026-01-03 19:50:45.781358361 +0200
@@ -462,6 +462,7 @@
extern VideoBootStrap WINDOWS_bootstrap;
extern VideoBootStrap WINRT_bootstrap;
@ -1672,7 +1684,7 @@ diff -ruN SDL2-2.32.8/src/video/SDL_sysvideo.h SDL2-2.32.8-banan_os/src/video/SD
extern VideoBootStrap Android_bootstrap;
diff -ruN SDL2-2.32.8/src/video/SDL_video.c SDL2-2.32.8-banan_os/src/video/SDL_video.c
--- SDL2-2.32.8/src/video/SDL_video.c 2025-05-20 00:24:41.000000000 +0300
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2026-01-07 19:04:34.398132645 +0200
+++ SDL2-2.32.8-banan_os/src/video/SDL_video.c 2026-01-03 19:50:45.782037083 +0200
@@ -96,6 +96,9 @@
#ifdef SDL_VIDEO_DRIVER_HAIKU
&HAIKU_bootstrap,

View File

@ -54,14 +54,9 @@ struct winsize
#define SND_GET_SAMPLE_RATE 61 /* stores sample rate to uint32_t argument */
#define SND_RESET_BUFFER 62 /* stores the size of internal buffer to uint32_t argument and clears the buffer */
#define SND_GET_BUFFERSZ 63 /* stores the size of internal buffer to uint32_t argument */
#define SND_GET_TOTAL_PINS 64 /* gets the number of pins on the current device as uint32_t */
#define SND_GET_PIN 65 /* gets the currently active pin as uint32_t */
#define SND_SET_PIN 66 /* sets the currently active pin to uint32_t */
#define JOYSTICK_GET_LEDS 80 /* get controller led bitmap to uint8_t argument */
#define JOYSTICK_SET_LEDS 81 /* set controller leds to uint8_t bitmap */
#define JOYSTICK_GET_RUMBLE 82 /* get controller rumble strength to uint8_t argument */
#define JOYSTICK_SET_RUMBLE 83 /* set controller rumble strength to uint8_t argument */
#define SND_GET_TOTAL_PINS 64 /* gets the number of pins on the current device */
#define SND_GET_PIN 65 /* gets the currently active pin */
#define SND_SET_PIN 66 /* sets the currently active pin */
int ioctl(int, int, ...);

View File

@ -5,45 +5,7 @@
namespace LibInput
{
enum JoystickButton
{
JSB_DPAD_UP,
JSB_DPAD_DOWN,
JSB_DPAD_LEFT,
JSB_DPAD_RIGHT,
JSB_FACE_UP,
JSB_FACE_DOWN,
JSB_FACE_LEFT,
JSB_FACE_RIGHT,
JSB_STICK_LEFT,
JSB_STICK_RIGHT,
JSB_SHOULDER_LEFT,
JSB_SHOULDER_RIGHT,
JSB_MENU,
JSB_START,
JSB_SELECT,
JSB_COUNT,
};
enum JoystickAxis
{
JSA_STICK_LEFT_X,
JSA_STICK_LEFT_Y,
JSA_STICK_RIGHT_X,
JSA_STICK_RIGHT_Y,
JSA_TRIGGER_LEFT,
JSA_TRIGGER_RIGHT,
JSA_COUNT,
};
// TODO: not used but exists if we ever make controller
// TODO: not used but here if we ever make controller
// support generating events instead of being polled
struct JoystickEvent
{
@ -52,9 +14,15 @@ namespace LibInput
struct JoystickState
{
// axis are mapped to range [-32767, +32767]
int16_t axis[JSA_COUNT];
bool buttons[JSB_COUNT];
struct Axis
{
int64_t value;
int64_t min;
int64_t max;
};
Axis axis[4];
bool buttons[32];
};
}

View File

@ -4,7 +4,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/framebuffer.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <termios.h>
@ -48,6 +47,13 @@ void cleanup()
tcsetattr(STDIN_FILENO, TCSANOW, &original_termios);
}
int map_joystick(const LibInput::JoystickState::Axis& axis, float min, float max)
{
if (axis.min == axis.max)
return (min + max) / 2;
return (axis.value - axis.min) * (max - min) / (axis.max - axis.min) + min;
}
int main(int argc, char** argv)
{
const char* fb_path = "/dev/fb0";
@ -126,12 +132,6 @@ int main(int argc, char** argv)
return 1;
}
uint8_t led_bitmap { 0b0001 };
ioctl(joystick_fd, JOYSTICK_SET_LEDS, &led_bitmap);
bool old_lshoulder { false }, old_rshoulder { false };
uint8_t rumble_strength { 0x00 };
uint32_t color = 0xFF0000;
int circle_x = fb_info.width / 2;
int circle_y = fb_info.height / 2;
@ -142,20 +142,9 @@ int main(int argc, char** argv)
draw_circle(circle_x, circle_y, radius, color);
msync(fb_mmap, fb_bytes, MS_SYNC);
timespec last_led_update;
clock_gettime(CLOCK_MONOTONIC, &last_led_update);
timespec prev_frame_ts;
clock_gettime(CLOCK_MONOTONIC, &prev_frame_ts);
while (true)
{
using namespace LibInput;
timespec current_ts;
clock_gettime(CLOCK_MONOTONIC, &current_ts);
JoystickState state {};
LibInput::JoystickState state {};
if (read(joystick_fd, &state, sizeof(state)) == -1)
{
fprintf(stderr, "read: ");
@ -163,9 +152,9 @@ int main(int argc, char** argv)
return 1;
}
const int dx = state.axis[JSA_STICK_LEFT_X] / 655;
const int dy = state.axis[JSA_STICK_LEFT_Y] / 655;
const int dr = state.axis[JSA_STICK_RIGHT_Y] / 6553;
const int dx = map_joystick(state.axis[0], -50, 50);
const int dy = map_joystick(state.axis[1], -50, 50);
const int dr = map_joystick(state.axis[3], 5, -5);
draw_circle(circle_x, circle_y, radius, 0x000000);
@ -175,59 +164,21 @@ int main(int argc, char** argv)
circle_y = BAN::Math::clamp<int>(circle_y + dy, 0, fb_info.height);
radius = BAN::Math::clamp<int>(radius + dr, 1, 100);
if (state.buttons[JSB_FACE_UP])
if (state.buttons[12])
color = 0xFF0000;
if (state.buttons[JSB_FACE_DOWN])
if (state.buttons[13])
color = 0x00FF00;
if (state.buttons[JSB_FACE_LEFT])
if (state.buttons[14])
color = 0x0000FF;
if (state.buttons[JSB_FACE_RIGHT])
if (state.buttons[15])
color = 0xFFFFFF;
if ((state.buttons[JSB_SHOULDER_LEFT] && !old_lshoulder) != (state.buttons[JSB_SHOULDER_RIGHT] && !old_rshoulder))
{
if (state.buttons[JSB_SHOULDER_LEFT] && !old_lshoulder)
led_bitmap = (led_bitmap - 1) & 0x0F;
if (state.buttons[JSB_SHOULDER_RIGHT] && !old_rshoulder)
led_bitmap = (led_bitmap + 1) & 0x0F;
ioctl(joystick_fd, JOYSTICK_SET_LEDS, &led_bitmap);
}
old_lshoulder = state.buttons[JSB_SHOULDER_LEFT];
old_rshoulder = state.buttons[JSB_SHOULDER_RIGHT];
if ((state.axis[JSA_TRIGGER_LEFT] > 0) != (state.axis[JSA_TRIGGER_RIGHT] > 0))
{
const auto old_rumble = rumble_strength;
if (state.axis[JSA_TRIGGER_LEFT] > 0)
rumble_strength = (rumble_strength <= 0x05) ? 0 : rumble_strength - 5;
if (state.axis[JSA_TRIGGER_RIGHT] > 0)
rumble_strength = (rumble_strength >= 0xFA) ? 0 : rumble_strength + 5;
if (rumble_strength != old_rumble)
ioctl(joystick_fd, JOYSTICK_SET_RUMBLE, &rumble_strength);
}
draw_circle(circle_x, circle_y, radius, color);
msync(fb_mmap, fb_bytes, MS_SYNC);
const uint64_t current_us =
current_ts.tv_sec * 1'000'000 +
current_ts.tv_nsec / 1000;
const uint64_t last_frame_us =
prev_frame_ts.tv_sec * 1'000'000 +
prev_frame_ts.tv_nsec / 1000;
usleep(16666);
const uint64_t wakeup_us = last_frame_us + 16'666;
if (current_us < wakeup_us)
{
const uint32_t sleep_us = wakeup_us - current_us;
const timespec sleep_ts {
.tv_sec = 0,
.tv_nsec = static_cast<long>(wakeup_us - current_us) * 1000,
};
nanosleep(&sleep_ts, nullptr);
}
prev_frame_ts = current_ts;
msync(fb_mmap, fb_bytes, MS_SYNC);
}
}