mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 20:41:45 +01:00
Fix evdev controller detection, add joystick squircling
This commit is contained in:
parent
e9f057c91b
commit
66a43c35db
@ -11,6 +11,7 @@
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
evdev_joystick_config g_evdev_joystick_config;
|
||||
|
||||
@ -20,8 +21,6 @@ namespace
|
||||
const u32 THREAD_SLEEP_INACTIVE_USEC = 1000000;
|
||||
const u32 READ_TIMEOUT = 10;
|
||||
const u32 THREAD_TIMEOUT_USEC = 1000000;
|
||||
|
||||
const std::string EVENT_JOYSTICK = "event-joystick";
|
||||
}
|
||||
|
||||
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.ryreverse);
|
||||
|
||||
fs::dir devdir{"/dev/input/by-path"};
|
||||
fs::dir devdir{"/dev/input/"};
|
||||
fs::dir_entry et;
|
||||
|
||||
while (devdir.read(et))
|
||||
{
|
||||
// Does the entry name end with event-joystick?
|
||||
if (et.name.size() > EVENT_JOYSTICK.size() &&
|
||||
et.name.compare(et.name.size() - EVENT_JOYSTICK.size(),
|
||||
EVENT_JOYSTICK.size(), EVENT_JOYSTICK) == 0)
|
||||
// Check if the entry starts with event (a 5-letter word)
|
||||
if (et.name.size() > 5 && et.name.compare(0, 5,"event") == 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_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_hat_ids.emplace_back(-1);
|
||||
m_pads.emplace_back(
|
||||
@ -111,6 +123,36 @@ void evdev_joystick_handler::update_devs()
|
||||
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)
|
||||
{
|
||||
libevdev*& dev = joy_devs[index];
|
||||
@ -395,8 +437,33 @@ void evdev_joystick_handler::thread_func()
|
||||
LOG_ERROR(GENERAL, "Joystick #%d sent axis event for invalid axis %d", i, axis);
|
||||
break;
|
||||
}
|
||||
|
||||
pad.m_sticks[axis].m_value = scale_axis(evt.code, evt.value);
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
|
||||
#define JOYSTICK_BUSTYPE 3
|
||||
|
||||
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 axistrigger{this, "Z axis triggers", true};
|
||||
cfg::_bool squirclejoysticks{this, "Squircle Joysticks", true};
|
||||
cfg::int32 squirclefactor{this, "Squircle Factor", 5000};
|
||||
|
||||
bool load()
|
||||
{
|
||||
@ -74,6 +77,7 @@ public:
|
||||
|
||||
private:
|
||||
void update_devs();
|
||||
std::tuple<u16, u16> ConvertToSquirclePoint(u16 inX, u16 inY);
|
||||
bool try_open_dev(u32 index);
|
||||
int scale_axis(int axis, int value);
|
||||
void thread_func();
|
||||
@ -84,6 +88,8 @@ private:
|
||||
std::vector<libevdev*> joy_devs;
|
||||
std::vector<std::vector<int>> joy_button_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;
|
||||
bool axistrigger;
|
||||
std::map<int, std::pair<int, int>> axis_ranges;
|
||||
|
Loading…
x
Reference in New Issue
Block a user