mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 23:11:25 +12:00
Fix evdev controller detection, add joystick squircling
This commit is contained in:
parent
e9f057c91b
commit
66a43c35db
2 changed files with 83 additions and 10 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
evdev_joystick_config g_evdev_joystick_config;
|
evdev_joystick_config g_evdev_joystick_config;
|
||||||
|
|
||||||
|
@ -20,8 +21,6 @@ namespace
|
||||||
const u32 THREAD_SLEEP_INACTIVE_USEC = 1000000;
|
const u32 THREAD_SLEEP_INACTIVE_USEC = 1000000;
|
||||||
const u32 READ_TIMEOUT = 10;
|
const u32 READ_TIMEOUT = 10;
|
||||||
const u32 THREAD_TIMEOUT_USEC = 1000000;
|
const u32 THREAD_TIMEOUT_USEC = 1000000;
|
||||||
|
|
||||||
const std::string EVENT_JOYSTICK = "event-joystick";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
evdev_joystick_handler::evdev_joystick_handler() {}
|
evdev_joystick_handler::evdev_joystick_handler() {}
|
||||||
|
@ -41,17 +40,29 @@ void evdev_joystick_handler::Init(const u32 max_connect)
|
||||||
revaxis.emplace_back(g_evdev_joystick_config.rxreverse);
|
revaxis.emplace_back(g_evdev_joystick_config.rxreverse);
|
||||||
revaxis.emplace_back(g_evdev_joystick_config.ryreverse);
|
revaxis.emplace_back(g_evdev_joystick_config.ryreverse);
|
||||||
|
|
||||||
fs::dir devdir{"/dev/input/by-path"};
|
fs::dir devdir{"/dev/input/"};
|
||||||
fs::dir_entry et;
|
fs::dir_entry et;
|
||||||
|
|
||||||
while (devdir.read(et))
|
while (devdir.read(et))
|
||||||
{
|
{
|
||||||
// Does the entry name end with event-joystick?
|
// Check if the entry starts with event (a 5-letter word)
|
||||||
if (et.name.size() > EVENT_JOYSTICK.size() &&
|
if (et.name.size() > 5 && et.name.compare(0, 5,"event") == 0)
|
||||||
et.name.compare(et.name.size() - EVENT_JOYSTICK.size(),
|
|
||||||
EVENT_JOYSTICK.size(), EVENT_JOYSTICK) == 0)
|
|
||||||
{
|
{
|
||||||
joy_paths.emplace_back(fmt::format("/dev/input/by-path/%s", et.name));
|
int fd = open(("/dev/input/" + et.name).c_str(), O_RDONLY|O_NONBLOCK);
|
||||||
|
struct libevdev *dev = NULL;
|
||||||
|
int rc = 1;
|
||||||
|
rc = libevdev_new_from_fd(fd, &dev);
|
||||||
|
if (rc < 0)
|
||||||
|
{
|
||||||
|
// If it's just a bad file descriptor, don't bother logging, but otherwise, log it.
|
||||||
|
if (rc == -9)
|
||||||
|
LOG_WARNING(GENERAL, "Failed to connect to device at %s, the error was: %s", "/dev/input/" + et.name, strerror(-rc));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (libevdev_get_id_bustype(dev) == JOYSTICK_BUSTYPE)
|
||||||
|
{
|
||||||
|
joy_paths.emplace_back(fmt::format("/dev/input/%s", et.name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +72,7 @@ void evdev_joystick_handler::Init(const u32 max_connect)
|
||||||
{
|
{
|
||||||
joy_devs.push_back(nullptr);
|
joy_devs.push_back(nullptr);
|
||||||
joy_axis_maps.emplace_back(ABS_RZ - ABS_X, -1);
|
joy_axis_maps.emplace_back(ABS_RZ - ABS_X, -1);
|
||||||
|
joy_axis.emplace_back(ABS_RZ - ABS_X, -1);
|
||||||
joy_button_maps.emplace_back(KEY_MAX - BTN_JOYSTICK, -1);
|
joy_button_maps.emplace_back(KEY_MAX - BTN_JOYSTICK, -1);
|
||||||
joy_hat_ids.emplace_back(-1);
|
joy_hat_ids.emplace_back(-1);
|
||||||
m_pads.emplace_back(
|
m_pads.emplace_back(
|
||||||
|
@ -111,6 +123,36 @@ void evdev_joystick_handler::update_devs()
|
||||||
m_info.now_connect = connected;
|
m_info.now_connect = connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline u16 Clamp0To255(f32 input)
|
||||||
|
{
|
||||||
|
if (input > 255.f)
|
||||||
|
return 255;
|
||||||
|
else if (input < 0.f)
|
||||||
|
return 0;
|
||||||
|
else return static_cast<u16>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<u16, u16> evdev_joystick_handler::ConvertToSquirclePoint(u16 inX, u16 inY)
|
||||||
|
{
|
||||||
|
// convert inX and Y to a (-1, 1) vector;
|
||||||
|
const f32 x = (inX - 127) / 127.f;
|
||||||
|
const f32 y = ((inY - 127) / 127.f);
|
||||||
|
|
||||||
|
// compute angle and len of given point to be used for squircle radius
|
||||||
|
const f32 angle = std::atan2(y, x);
|
||||||
|
const f32 r = std::sqrt(std::pow(x, 2.f) + std::pow(y, 2.f));
|
||||||
|
|
||||||
|
// now find len/point on the given squircle from our current angle and radius in polar coords
|
||||||
|
// https://thatsmaths.com/2016/07/14/squircles/
|
||||||
|
const f32 newLen = (1 + std::pow(std::sin(2 * angle), 2.f) / (g_evdev_joystick_config.squirclefactor / 1000.f)) * r;
|
||||||
|
|
||||||
|
// we now have len and angle, convert to cartisian
|
||||||
|
|
||||||
|
const int newX = Clamp0To255(((newLen * std::cos(angle)) + 1) * 127);
|
||||||
|
const int newY = Clamp0To255(((newLen * std::sin(angle)) + 1) * 127);
|
||||||
|
return std::tuple<u16, u16>(newX, newY);
|
||||||
|
}
|
||||||
|
|
||||||
bool evdev_joystick_handler::try_open_dev(u32 index)
|
bool evdev_joystick_handler::try_open_dev(u32 index)
|
||||||
{
|
{
|
||||||
libevdev*& dev = joy_devs[index];
|
libevdev*& dev = joy_devs[index];
|
||||||
|
@ -396,6 +438,31 @@ void evdev_joystick_handler::thread_func()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_evdev_joystick_config.squirclejoysticks)
|
||||||
|
{
|
||||||
|
joy_axis[i][axis] = evt.value;
|
||||||
|
if (evt.code == ABS_X || evt.code == ABS_Y)
|
||||||
|
{
|
||||||
|
int Xaxis = joy_axis_maps[i][ABS_X];
|
||||||
|
int Yaxis = joy_axis_maps[i][ABS_Y];
|
||||||
|
pad.m_sticks[Xaxis].m_value = scale_axis(ABS_X, joy_axis[i][Xaxis]);
|
||||||
|
pad.m_sticks[Yaxis].m_value = scale_axis(ABS_Y, joy_axis[i][Yaxis]);
|
||||||
|
|
||||||
|
std::tie(pad.m_sticks[Xaxis].m_value, pad.m_sticks[Yaxis].m_value) =
|
||||||
|
ConvertToSquirclePoint(pad.m_sticks[Xaxis].m_value, pad.m_sticks[Yaxis].m_value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int Xaxis = joy_axis_maps[i][ABS_RX];
|
||||||
|
int Yaxis = joy_axis_maps[i][ABS_RY];
|
||||||
|
pad.m_sticks[Xaxis].m_value = scale_axis(ABS_RX, joy_axis[i][Xaxis]);
|
||||||
|
pad.m_sticks[Yaxis].m_value = scale_axis(ABS_RY, joy_axis[i][Yaxis]);
|
||||||
|
|
||||||
|
std::tie(pad.m_sticks[Xaxis].m_value, pad.m_sticks[Yaxis].m_value) =
|
||||||
|
ConvertToSquirclePoint(pad.m_sticks[Xaxis].m_value, pad.m_sticks[Yaxis].m_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
pad.m_sticks[axis].m_value = scale_axis(evt.code, evt.value);
|
pad.m_sticks[axis].m_value = scale_axis(evt.code, evt.value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#define JOYSTICK_BUSTYPE 3
|
||||||
|
|
||||||
enum { EVDEV_DPAD_HAT_AXIS_X = -1, EVDEV_DPAD_HAT_AXIS_Y = -2 };
|
enum { EVDEV_DPAD_HAT_AXIS_X = -1, EVDEV_DPAD_HAT_AXIS_Y = -2 };
|
||||||
|
|
||||||
|
@ -45,6 +46,8 @@ struct evdev_joystick_config final : cfg::node
|
||||||
cfg::_bool lyreverse{this, "Reverse left stick Y axis", false};
|
cfg::_bool lyreverse{this, "Reverse left stick Y axis", false};
|
||||||
|
|
||||||
cfg::_bool axistrigger{this, "Z axis triggers", true};
|
cfg::_bool axistrigger{this, "Z axis triggers", true};
|
||||||
|
cfg::_bool squirclejoysticks{this, "Squircle Joysticks", true};
|
||||||
|
cfg::int32 squirclefactor{this, "Squircle Factor", 5000};
|
||||||
|
|
||||||
bool load()
|
bool load()
|
||||||
{
|
{
|
||||||
|
@ -74,6 +77,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void update_devs();
|
void update_devs();
|
||||||
|
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY);
|
||||||
bool try_open_dev(u32 index);
|
bool try_open_dev(u32 index);
|
||||||
int scale_axis(int axis, int value);
|
int scale_axis(int axis, int value);
|
||||||
void thread_func();
|
void thread_func();
|
||||||
|
@ -84,6 +88,8 @@ private:
|
||||||
std::vector<libevdev*> joy_devs;
|
std::vector<libevdev*> joy_devs;
|
||||||
std::vector<std::vector<int>> joy_button_maps;
|
std::vector<std::vector<int>> joy_button_maps;
|
||||||
std::vector<std::vector<int>> joy_axis_maps;
|
std::vector<std::vector<int>> joy_axis_maps;
|
||||||
|
// joy_axis is only used for squircling
|
||||||
|
std::vector<std::vector<int>> joy_axis;
|
||||||
std::vector<int> joy_hat_ids;
|
std::vector<int> joy_hat_ids;
|
||||||
bool axistrigger;
|
bool axistrigger;
|
||||||
std::map<int, std::pair<int, int>> axis_ranges;
|
std::map<int, std::pair<int, int>> axis_ranges;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue