summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2019-11-08 18:23:22 -0600
committerJordan Woyak <jordan.woyak@gmail.com>2019-11-09 13:34:29 -0600
commit1180c231a697297f468020a56db236ef795101e5 (patch)
treeca014c368b1bbb8ad003c459385c337ab481a51f /Source/Core/InputCommon/ControllerInterface
parentd8c62b5965df694fb5f93b617e356cae1f9441b7 (diff)
InputCommon: Detect when evdev exposes acceleration/gyroscope data.
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp2
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp197
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.h28
3 files changed, 152 insertions, 75 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp
index 60086d517c..9ed62e5285 100644
--- a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp
@@ -108,7 +108,7 @@ private:
int m_touch_y;
};
-static constexpr double GRAVITY_ACCELERATION = 9.80665;
+using MathUtil::GRAVITY_ACCELERATION;
static constexpr char DEFAULT_SERVER_ADDRESS[] = "127.0.0.1";
static constexpr u16 DEFAULT_SERVER_PORT = 26760;
static constexpr auto SERVER_REREGISTER_INTERVAL = std::chrono::seconds{1};
diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
index de14875f56..8aed987a2a 100644
--- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
@@ -25,6 +25,121 @@
namespace ciface::evdev
{
+class Input : public Core::Device::Input
+{
+public:
+ Input(u16 code, libevdev* dev) : m_code(code), m_dev(dev) {}
+
+protected:
+ const u16 m_code;
+ libevdev* const m_dev;
+};
+
+class Button final : public Input
+{
+public:
+ Button(u8 index, u16 code, libevdev* dev) : Input(code, dev), m_index(index) {}
+
+ std::string GetName() const override
+ {
+ // Buttons below 0x100 are mostly keyboard keys, and the names make sense
+ if (m_code < 0x100)
+ {
+ const char* name = libevdev_event_code_get_name(EV_KEY, m_code);
+ if (name)
+ return std::string(StripSpaces(name));
+ }
+ // But controllers use codes above 0x100, and the standard label often doesn't match.
+ // We are better off with Button 0 and so on.
+ return "Button " + std::to_string(m_index);
+ }
+
+ ControlState GetState() const override
+ {
+ int value = 0;
+ libevdev_fetch_event_value(m_dev, EV_KEY, m_code, &value);
+ return value;
+ }
+
+private:
+ const u8 m_index;
+};
+
+class AnalogInput : public Input
+{
+public:
+ using Input::Input;
+
+ ControlState GetState() const override
+ {
+ int value = 0;
+ libevdev_fetch_event_value(m_dev, EV_ABS, m_code, &value);
+
+ return ControlState(value - m_base) / m_range;
+ }
+
+protected:
+ int m_range;
+ int m_base;
+};
+
+class Axis final : public AnalogInput
+{
+public:
+ Axis(u8 index, u16 code, bool upper, libevdev* dev) : AnalogInput(code, dev), m_index(index)
+ {
+ const int min = libevdev_get_abs_minimum(m_dev, m_code);
+ const int max = libevdev_get_abs_maximum(m_dev, m_code);
+
+ m_base = (max + min) / 2;
+ m_range = (upper ? max : min) - m_base;
+ }
+
+ std::string GetName() const override
+ {
+ return "Axis " + std::to_string(m_index) + (m_range < 0 ? '-' : '+');
+ }
+
+private:
+ const u8 m_index;
+};
+
+class MotionDataInput final : public AnalogInput
+{
+public:
+ MotionDataInput(u16 code, ControlState resolution_scale, libevdev* dev) : AnalogInput(code, dev)
+ {
+ auto* const info = libevdev_get_abs_info(m_dev, m_code);
+
+ // The average of the minimum and maximum value. (neutral value)
+ m_base = (info->maximum + info->minimum) / 2;
+
+ m_range = info->resolution / resolution_scale;
+ }
+
+ std::string GetName() const override
+ {
+ // Unfortunately there doesn't seem to be a "standard" orientation
+ // so we can't use "Accel Up"-like names.
+ constexpr std::array<const char*, 6> motion_data_names = {{
+ "Accel X",
+ "Accel Y",
+ "Accel Z",
+ "Gyro X",
+ "Gyro Y",
+ "Gyro Z",
+ }};
+
+ // Our name array relies on sane axis codes from 0 to 5.
+ static_assert(ABS_X == 0, "evdev axis value sanity check");
+ static_assert(ABS_RX == 3, "evdev axis value sanity check");
+
+ return std::string(motion_data_names[m_code]) + (m_range < 0 ? '-' : '+');
+ }
+
+ bool IsDetectable() override { return false; }
+};
+
static std::thread s_hotplug_thread;
static Common::Flag s_hotplug_thread_running;
static int s_wakeup_eventfd;
@@ -213,9 +328,43 @@ evdevDevice::evdevDevice(const std::string& devnode) : m_devfile(devnode)
AddInput(new Button(num_buttons++, key, m_dev));
}
+ int first_axis_code = 0;
+
+ int num_motion_axis = 0;
+ if (libevdev_has_property(m_dev, INPUT_PROP_ACCELEROMETER))
+ {
+ // If INPUT_PROP_ACCELEROMETER is set then X,Y,Z,RX,RY,RZ contain motion data.
+
+ auto add_motion_inputs = [&num_motion_axis, this](int first_code, double scale) {
+ for (int i = 0; i != 3; ++i)
+ {
+ const int code = first_code + i;
+ if (libevdev_has_event_code(m_dev, EV_ABS, code))
+ {
+ AddInput(new MotionDataInput(code, scale * -1, m_dev));
+ AddInput(new MotionDataInput(code, scale, m_dev));
+
+ ++num_motion_axis;
+ }
+ }
+ };
+
+ // evdev resolution is specified in "g"s and deg/s.
+ // Convert these to m/s/s and rad/s.
+ constexpr ControlState accel_scale = MathUtil::GRAVITY_ACCELERATION;
+ constexpr ControlState gyro_scale = MathUtil::TAU / 360;
+
+ add_motion_inputs(ABS_X, accel_scale);
+ add_motion_inputs(ABS_RX, gyro_scale);
+
+ // evdev says regular axes should not be mixed with motion data,
+ // but we'll keep looking for regular axes after RZ just in case.
+ first_axis_code = ABS_RZ + 1;
+ }
+
// Absolute axis (thumbsticks)
int num_axis = 0;
- for (int axis = 0; axis < 0x100; axis++)
+ for (int axis = first_axis_code; axis != ABS_CNT; ++axis)
{
if (libevdev_has_event_code(m_dev, EV_ABS, axis))
{
@@ -262,7 +411,7 @@ evdevDevice::evdevDevice(const std::string& devnode) : m_devfile(devnode)
// TODO: Add leds as output devices
// Was there some reasoning behind these numbers?
- m_interesting = num_axis >= 2 || num_buttons >= 8;
+ m_interesting = num_motion_axis != 0 || num_axis >= 2 || num_buttons >= 8;
}
evdevDevice::~evdevDevice()
@@ -306,50 +455,6 @@ bool evdevDevice::IsValid() const
return true;
}
-std::string evdevDevice::Button::GetName() const
-{
- // Buttons below 0x100 are mostly keyboard keys, and the names make sense
- if (m_code < 0x100)
- {
- const char* name = libevdev_event_code_get_name(EV_KEY, m_code);
- if (name)
- return std::string(StripSpaces(name));
- }
- // But controllers use codes above 0x100, and the standard label often doesn't match.
- // We are better off with Button 0 and so on.
- return "Button " + std::to_string(m_index);
-}
-
-ControlState evdevDevice::Button::GetState() const
-{
- int value = 0;
- libevdev_fetch_event_value(m_dev, EV_KEY, m_code, &value);
- return value;
-}
-
-evdevDevice::Axis::Axis(u8 index, u16 code, bool upper, libevdev* dev)
- : m_code(code), m_index(index), m_dev(dev)
-{
- const int min = libevdev_get_abs_minimum(m_dev, m_code);
- const int max = libevdev_get_abs_maximum(m_dev, m_code);
-
- m_base = (max + min) / 2;
- m_range = (upper ? max : min) - m_base;
-}
-
-std::string evdevDevice::Axis::GetName() const
-{
- return "Axis " + std::to_string(m_index) + (m_range < 0 ? '-' : '+');
-}
-
-ControlState evdevDevice::Axis::GetState() const
-{
- int value = 0;
- libevdev_fetch_event_value(m_dev, EV_ABS, m_code, &value);
-
- return ControlState(value - m_base) / m_range;
-}
-
evdevDevice::Effect::Effect(int fd) : m_fd(fd)
{
m_effect.id = -1;
diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
index 9f2996b420..f4b095558b 100644
--- a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
+++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
@@ -19,34 +19,6 @@ void Shutdown();
class evdevDevice : public Core::Device
{
private:
- class Button : public Core::Device::Input
- {
- public:
- std::string GetName() const override;
- Button(u8 index, u16 code, libevdev* dev) : m_index(index), m_code(code), m_dev(dev) {}
- ControlState GetState() const override;
-
- private:
- const u8 m_index;
- const u16 m_code;
- libevdev* m_dev;
- };
-
- class Axis : public Core::Device::Input
- {
- public:
- std::string GetName() const override;
- Axis(u8 index, u16 code, bool upper, libevdev* dev);
- ControlState GetState() const override;
-
- private:
- const u16 m_code;
- const u8 m_index;
- int m_range;
- int m_base;
- libevdev* m_dev;
- };
-
class Effect : public Core::Device::Output
{
public: