summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface
diff options
context:
space:
mode:
authorLinktothepast <kostamarino@gmail.com>2015-09-28 16:50:35 +0300
committerLinktothepast <kostamarino@gmail.com>2015-09-28 16:50:35 +0300
commit748be565b8df535ef558e74b38cd0f4d615f8a21 (patch)
treeb151efee0a87e99125f2401325a9bddecf84fc73 /Source/Core/InputCommon/ControllerInterface
parentcf17fccdd3093a1b8476b10183b1c4bde36da74d (diff)
parentce493b897d6d3735c930a8465cc0c26bbe5feb86 (diff)
Merge remote-tracking branch 'dolphin-emu/master' into gameinis
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Android/Android.cpp20
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp6
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ControllerInterface.h3
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.h24
-rw-r--r--Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h32
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Device.h2
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ExpressionParser.cpp30
-rw-r--r--Source/Core/InputCommon/ControllerInterface/ForceFeedback/ForceFeedbackDevice.h5
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h20
-rw-r--r--Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h14
-rw-r--r--Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp2
-rw-r--r--Source/Core/InputCommon/ControllerInterface/XInput/XInput.h30
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp305
-rw-r--r--Source/Core/InputCommon/ControllerInterface/evdev/evdev.h87
14 files changed, 501 insertions, 79 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
index b0539b520f..7cf0f628bd 100644
--- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp
@@ -17,6 +17,10 @@ void Init( std::vector<Core::Device*>& devices )
devices.push_back(new Touchscreen(1));
devices.push_back(new Touchscreen(2));
devices.push_back(new Touchscreen(3));
+ devices.push_back(new Touchscreen(4));
+ devices.push_back(new Touchscreen(5));
+ devices.push_back(new Touchscreen(6));
+ devices.push_back(new Touchscreen(7));
}
// Touchscreens and stuff
@@ -32,11 +36,12 @@ std::string Touchscreen::GetSource() const
int Touchscreen::GetId() const
{
- return 0;
+ return _padID;
}
Touchscreen::Touchscreen(int padID)
: _padID(padID)
{
+ // GC
AddInput(new Button(_padID, ButtonManager::BUTTON_A));
AddInput(new Button(_padID, ButtonManager::BUTTON_B));
AddInput(new Button(_padID, ButtonManager::BUTTON_START));
@@ -53,6 +58,19 @@ Touchscreen::Touchscreen(int padID)
AddAnalogInputs(new Axis(_padID, ButtonManager::STICK_C_UP), new Axis(_padID, ButtonManager::STICK_C_DOWN));
AddAnalogInputs(new Axis(_padID, ButtonManager::TRIGGER_L), new Axis(_padID, ButtonManager::TRIGGER_L));
AddAnalogInputs(new Axis(_padID, ButtonManager::TRIGGER_R), new Axis(_padID, ButtonManager::TRIGGER_R));
+
+ // Wiimote
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_A));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_B));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_MINUS));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_PLUS));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_HOME));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_1));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_BUTTON_2));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_UP));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_DOWN));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_LEFT));
+ AddInput(new Button(_padID, ButtonManager::WIIMOTE_RIGHT));
}
// Buttons and stuff
diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
index 6b8b11fd3a..0631069e16 100644
--- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp
@@ -26,6 +26,9 @@
#ifdef CIFACE_USE_ANDROID
#include "InputCommon/ControllerInterface/Android/Android.h"
#endif
+#ifdef CIFACE_USE_EVDEV
+ #include "InputCommon/ControllerInterface/evdev/evdev.h"
+#endif
using namespace ciface::ExpressionParser;
@@ -69,6 +72,9 @@ void ControllerInterface::Initialize(void* const hwnd)
#ifdef CIFACE_USE_ANDROID
ciface::Android::Init(m_devices);
#endif
+#ifdef CIFACE_USE_EVDEV
+ ciface::evdev::Init(m_devices);
+#endif
m_is_init = true;
}
diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
index 408a36fefa..3aca18e95c 100644
--- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
+++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h
@@ -35,6 +35,9 @@
#if defined(HAVE_SDL) && HAVE_SDL
#define CIFACE_USE_SDL
#endif
+#if defined(HAVE_LIBEVDEV) && defined(HAVE_LIBUDEV)
+ #define CIFACE_USE_EVDEV
+#endif
//
// ControllerInterface
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.h b/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.h
index c89ba509d3..3064051101 100644
--- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.h
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputJoystick.h
@@ -20,9 +20,9 @@ private:
class Button : public Input
{
public:
- std::string GetName() const;
- Button(u8 index, const BYTE& button) : m_index(index), m_button(button) {}
- ControlState GetState() const;
+ Button(u8 index, const BYTE& button) : m_button(button), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const BYTE& m_button;
const u8 m_index;
@@ -31,9 +31,9 @@ private:
class Axis : public Input
{
public:
- std::string GetName() const;
- Axis(u8 index, const LONG& axis, LONG base, LONG range) : m_index(index), m_axis(axis), m_base(base), m_range(range) {}
- ControlState GetState() const;
+ Axis(u8 index, const LONG& axis, LONG base, LONG range) : m_axis(axis), m_base(base), m_range(range), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const LONG& m_axis;
const LONG m_base, m_range;
@@ -43,9 +43,9 @@ private:
class Hat : public Input
{
public:
- std::string GetName() const;
- Hat(u8 index, const DWORD& hat, u8 direction) : m_index(index), m_hat(hat), m_direction(direction) {}
- ControlState GetState() const;
+ Hat(u8 index, const DWORD& hat, u8 direction) : m_hat(hat), m_direction(direction), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const DWORD& m_hat;
const u8 m_index, m_direction;
@@ -57,9 +57,9 @@ public:
Joystick(const LPDIRECTINPUTDEVICE8 device, const unsigned int index);
~Joystick();
- std::string GetName() const;
- int GetId() const;
- std::string GetSource() const;
+ std::string GetName() const override;
+ int GetId() const override;
+ std::string GetSource() const override;
private:
const LPDIRECTINPUTDEVICE8 m_device;
diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
index db4d363df0..14d885ff94 100644
--- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
+++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h
@@ -32,9 +32,9 @@ private:
class Key : public Input
{
public:
- std::string GetName() const;
- Key(u8 index, const BYTE& key) : m_index(index), m_key(key) {}
- ControlState GetState() const;
+ Key(u8 index, const BYTE& key) : m_key(key), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const BYTE& m_key;
const u8 m_index;
@@ -43,9 +43,9 @@ private:
class Button : public Input
{
public:
- std::string GetName() const;
- Button(u8 index, const BYTE& button) : m_index(index), m_button(button) {}
- ControlState GetState() const;
+ Button(u8 index, const BYTE& button) : m_button(button), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const BYTE& m_button;
const u8 m_index;
@@ -54,9 +54,9 @@ private:
class Axis : public Input
{
public:
- std::string GetName() const;
- Axis(u8 index, const LONG& axis, LONG range) : m_index(index), m_axis(axis), m_range(range) {}
- ControlState GetState() const;
+ Axis(u8 index, const LONG& axis, LONG range) : m_axis(axis), m_range(range), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const LONG& m_axis;
const LONG m_range;
@@ -66,10 +66,10 @@ private:
class Cursor : public Input
{
public:
- std::string GetName() const;
- bool IsDetectable() { return false; }
- Cursor(u8 index, const ControlState& axis, const bool positive) : m_index(index), m_axis(axis), m_positive(positive) {}
- ControlState GetState() const;
+ Cursor(u8 index, const ControlState& axis, const bool positive) : m_axis(axis), m_index(index), m_positive(positive) {}
+ std::string GetName() const override;
+ bool IsDetectable() override { return false; }
+ ControlState GetState() const override;
private:
const ControlState& m_axis;
const u8 m_index;
@@ -82,9 +82,9 @@ public:
KeyboardMouse(const LPDIRECTINPUTDEVICE8 kb_device, const LPDIRECTINPUTDEVICE8 mo_device);
~KeyboardMouse();
- std::string GetName() const;
- int GetId() const;
- std::string GetSource() const;
+ std::string GetName() const override;
+ int GetId() const override;
+ std::string GetSource() const override;
private:
const LPDIRECTINPUTDEVICE8 m_kb_device;
diff --git a/Source/Core/InputCommon/ControllerInterface/Device.h b/Source/Core/InputCommon/ControllerInterface/Device.h
index c27910af5d..7e6172149f 100644
--- a/Source/Core/InputCommon/ControllerInterface/Device.h
+++ b/Source/Core/InputCommon/ControllerInterface/Device.h
@@ -61,8 +61,6 @@ public:
virtual ControlState GetState() const = 0;
- bool ShouldHaveInput();
-
ControlState GetGatedState()
{
if (InputGateOn())
diff --git a/Source/Core/InputCommon/ControllerInterface/ExpressionParser.cpp b/Source/Core/InputCommon/ControllerInterface/ExpressionParser.cpp
index 9837ea74cb..bcb2c95a96 100644
--- a/Source/Core/InputCommon/ControllerInterface/ExpressionParser.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/ExpressionParser.cpp
@@ -63,8 +63,6 @@ public:
{
switch (type)
{
- case TOK_INVALID:
- return "Invalid";
case TOK_DISCARD:
return "Discard";
case TOK_EOF:
@@ -83,7 +81,11 @@ public:
return "+";
case TOK_CONTROL:
return "Device(" + (std::string)qualifier + ")";
+ case TOK_INVALID:
+ break;
}
+
+ return "Invalid";
}
};
@@ -254,22 +256,22 @@ public:
ControlExpression(ControlQualifier qualifier_, Device::Control *control_) : qualifier(qualifier_), control(control_) {}
- virtual ControlState GetValue() override
+ ControlState GetValue() override
{
return control->ToInput()->GetGatedState();
}
- virtual void SetValue(ControlState value) override
+ void SetValue(ControlState value) override
{
control->ToOutput()->SetGatedState(value);
}
- virtual int CountNumControls() override
+ int CountNumControls() override
{
return 1;
}
- virtual operator std::string() override
+ operator std::string() override
{
return "`" + (std::string)qualifier + "`";
}
@@ -289,7 +291,7 @@ public:
delete rhs;
}
- virtual ControlState GetValue() override
+ ControlState GetValue() override
{
ControlState lhsValue = lhs->GetValue();
ControlState rhsValue = rhs->GetValue();
@@ -307,7 +309,7 @@ public:
}
}
- virtual void SetValue(ControlState value) override
+ void SetValue(ControlState value) override
{
// Don't do anything special with the op we have.
// Treat "A & B" the same as "A | B".
@@ -315,12 +317,12 @@ public:
rhs->SetValue(value);
}
- virtual int CountNumControls() override
+ int CountNumControls() override
{
return lhs->CountNumControls() + rhs->CountNumControls();
}
- virtual operator std::string() override
+ operator std::string() override
{
return OpName(op) + "(" + (std::string)(*lhs) + ", " + (std::string)(*rhs) + ")";
}
@@ -338,7 +340,7 @@ public:
delete inner;
}
- virtual ControlState GetValue() override
+ ControlState GetValue() override
{
ControlState value = inner->GetValue();
switch (op)
@@ -351,7 +353,7 @@ public:
}
}
- virtual void SetValue(ControlState value) override
+ void SetValue(ControlState value) override
{
switch (op)
{
@@ -364,12 +366,12 @@ public:
}
}
- virtual int CountNumControls() override
+ int CountNumControls() override
{
return inner->CountNumControls();
}
- virtual operator std::string() override
+ operator std::string() override
{
return OpName(op) + "(" + (std::string)(*inner) + ")";
}
diff --git a/Source/Core/InputCommon/ControllerInterface/ForceFeedback/ForceFeedbackDevice.h b/Source/Core/InputCommon/ControllerInterface/ForceFeedback/ForceFeedbackDevice.h
index a528c00602..f49198f037 100644
--- a/Source/Core/InputCommon/ControllerInterface/ForceFeedback/ForceFeedbackDevice.h
+++ b/Source/Core/InputCommon/ControllerInterface/ForceFeedback/ForceFeedbackDevice.h
@@ -29,10 +29,11 @@ private:
class Force : public Output
{
public:
- std::string GetName() const;
Force(const std::string& name, LPDIRECTINPUTEFFECT iface);
~Force();
- void SetState(ControlState state);
+
+ std::string GetName() const override;
+ void SetState(ControlState state) override;
void Update();
void Stop();
private:
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h
index c0fdec5537..d0ed715130 100644
--- a/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXJoystick.h
@@ -20,10 +20,10 @@ private:
class Button : public Input
{
public:
- std::string GetName() const;
Button(IOHIDElementRef element, IOHIDDeviceRef device)
: m_element(element), m_device(device) {}
- ControlState GetState() const;
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const IOHIDElementRef m_element;
const IOHIDDeviceRef m_device;
@@ -37,9 +37,10 @@ private:
positive = 0,
negative
};
- std::string GetName() const;
+
Axis(IOHIDElementRef element, IOHIDDeviceRef device, direction dir);
- ControlState GetState() const;
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const IOHIDElementRef m_element;
@@ -60,9 +61,10 @@ private:
down,
left
};
- std::string GetName() const;
+
Hat(IOHIDElementRef element, IOHIDDeviceRef device, direction dir);
- ControlState GetState() const;
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const IOHIDElementRef m_element;
@@ -75,9 +77,9 @@ public:
Joystick(IOHIDDeviceRef device, std::string name, int index);
~Joystick();
- std::string GetName() const;
- std::string GetSource() const;
- int GetId() const;
+ std::string GetName() const override;
+ std::string GetSource() const override;
+ int GetId() const override;
private:
const IOHIDDeviceRef m_device;
diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h
index 4be67a503c..d404f90684 100644
--- a/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h
+++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSXKeyboard.h
@@ -19,9 +19,9 @@ private:
class Key : public Input
{
public:
- std::string GetName() const;
Key(IOHIDElementRef element, IOHIDDeviceRef device);
- ControlState GetState() const;
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const IOHIDElementRef m_element;
const IOHIDDeviceRef m_device;
@@ -31,10 +31,10 @@ private:
class Cursor : public Input
{
public:
- std::string GetName() const;
- bool IsDetectable() { return false; }
Cursor(u8 index, const float& axis, const bool positive) : m_axis(axis), m_index(index), m_positive(positive) {}
- ControlState GetState() const;
+ std::string GetName() const override;
+ bool IsDetectable() override { return false; }
+ ControlState GetState() const override;
private:
const float& m_axis;
const u8 m_index;
@@ -44,9 +44,9 @@ private:
class Button : public Input
{
public:
- std::string GetName() const;
Button(u8 index, const unsigned char& button) : m_button(button), m_index(index) {}
- ControlState GetState() const;
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const unsigned char& m_button;
const u8 m_index;
diff --git a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp
index 0e2c0bcad3..1ee374d483 100644
--- a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.cpp
@@ -122,7 +122,7 @@ void DeInit()
}
Device::Device(const XINPUT_CAPABILITIES& caps, u8 index)
- : m_index(index), m_subtype(caps.SubType)
+ : m_subtype(caps.SubType), m_index(index)
{
ZeroMemory(&m_state_out, sizeof(m_state_out));
diff --git a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h
index 5dcfb0cee5..59a3f6ff79 100644
--- a/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h
+++ b/Source/Core/InputCommon/ControllerInterface/XInput/XInput.h
@@ -32,9 +32,9 @@ private:
class Button : public Core::Device::Input
{
public:
- std::string GetName() const;
- Button(u8 index, const WORD& buttons) : m_index(index), m_buttons(buttons) {}
- ControlState GetState() const;
+ Button(u8 index, const WORD& buttons) : m_buttons(buttons), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const WORD& m_buttons;
u8 m_index;
@@ -43,9 +43,9 @@ private:
class Axis : public Core::Device::Input
{
public:
- std::string GetName() const;
- Axis(u8 index, const SHORT& axis, SHORT range) : m_index(index), m_axis(axis), m_range(range) {}
- ControlState GetState() const;
+ Axis(u8 index, const SHORT& axis, SHORT range) : m_axis(axis), m_range(range), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const SHORT& m_axis;
const SHORT m_range;
@@ -55,9 +55,9 @@ private:
class Trigger : public Core::Device::Input
{
public:
- std::string GetName() const;
- Trigger(u8 index, const BYTE& trigger, BYTE range) : m_index(index), m_trigger(trigger), m_range(range) {}
- ControlState GetState() const;
+ Trigger(u8 index, const BYTE& trigger, BYTE range) : m_trigger(trigger), m_range(range), m_index(index) {}
+ std::string GetName() const override;
+ ControlState GetState() const override;
private:
const BYTE& m_trigger;
const BYTE m_range;
@@ -67,9 +67,9 @@ private:
class Motor : public Core::Device::Output
{
public:
- std::string GetName() const;
- Motor(u8 index, Device* parent, WORD &motor, WORD range) : m_index(index), m_parent(parent), m_motor(motor), m_range(range) {}
- void SetState(ControlState state);
+ Motor(u8 index, Device* parent, WORD &motor, WORD range) : m_motor(motor), m_range(range), m_index(index), m_parent(parent) {}
+ std::string GetName() const override;
+ void SetState(ControlState state) override;
private:
WORD& m_motor;
const WORD m_range;
@@ -82,9 +82,9 @@ public:
Device(const XINPUT_CAPABILITIES& capabilities, u8 index);
- std::string GetName() const;
- int GetId() const;
- std::string GetSource() const;
+ std::string GetName() const override;
+ int GetId() const override;
+ std::string GetSource() const override;
void UpdateMotors();
diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
new file mode 100644
index 0000000000..d88a44b7ef
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.cpp
@@ -0,0 +1,305 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include <fcntl.h>
+#include <libudev.h>
+#include <map>
+#include <unistd.h>
+
+#include "Common/Assert.h"
+#include "Common/Logging/Log.h"
+#include "InputCommon/ControllerInterface/evdev/evdev.h"
+
+
+namespace ciface
+{
+namespace evdev
+{
+
+static std::string GetName(const std::string& devnode)
+{
+ int fd = open(devnode.c_str(), O_RDWR|O_NONBLOCK);
+ libevdev* dev = nullptr;
+ int ret = libevdev_new_from_fd(fd, &dev);
+ if (ret != 0)
+ {
+ close(fd);
+ return std::string();
+ }
+ std::string res = libevdev_get_name(dev);
+ libevdev_free(dev);
+ close(fd);
+ return res;
+}
+
+void Init(std::vector<Core::Device*> &controllerDevices)
+{
+ // this is used to number the joysticks
+ // multiple joysticks with the same name shall get unique ids starting at 0
+ std::map<std::string, int> name_counts;
+
+ int num_controllers = 0;
+
+ // We use Udev to find any devices. In the future this will allow for hotplugging.
+ // But for now it is essentially iterating over /dev/input/event0 to event31. However if the
+ // naming scheme is ever updated in the future, this *should* be forwards compatable.
+
+ struct udev* udev = udev_new();
+ _assert_msg_(PAD, udev != 0, "Couldn't initilize libudev.");
+
+ // List all input devices
+ udev_enumerate* enumerate = udev_enumerate_new(udev);
+ udev_enumerate_add_match_subsystem(enumerate, "input");
+ udev_enumerate_scan_devices(enumerate);
+ udev_list_entry* devices = udev_enumerate_get_list_entry(enumerate);
+
+ // Iterate over all input devices
+ udev_list_entry* dev_list_entry;
+ udev_list_entry_foreach(dev_list_entry, devices)
+ {
+ const char* path = udev_list_entry_get_name(dev_list_entry);
+
+ udev_device* dev = udev_device_new_from_syspath(udev, path);
+
+ const char* devnode = udev_device_get_devnode(dev);
+ // We only care about devices which we have read/write access to.
+ if (devnode && access(devnode, W_OK) == 0)
+ {
+ // Unfortunately udev gives us no way to filter out the non event device interfaces.
+ // So we open it and see if it works with evdev ioctls or not.
+ std::string name = GetName(devnode);
+ evdevDevice* input = new evdevDevice(devnode, name_counts[name]++);
+
+ if (input->IsInteresting())
+ {
+ controllerDevices.push_back(input);
+ num_controllers++;
+ }
+ else
+ {
+ // Either it wasn't a evdev device, or it didn't have at least 8 buttons or two axis.
+ delete input;
+ }
+ }
+ udev_device_unref(dev);
+ }
+ udev_enumerate_unref(enumerate);
+ udev_unref(udev);
+}
+
+evdevDevice::evdevDevice(const std::string &devnode, int id) : m_devfile(devnode), m_id(id)
+{
+ // The device file will be read on one of the main threads, so we open in non-blocking mode.
+ m_fd = open(devnode.c_str(), O_RDWR|O_NONBLOCK);
+ int ret = libevdev_new_from_fd(m_fd, &m_dev);
+
+ if (ret != 0)
+ {
+ // This useally fails because the device node isn't an evdev device, such as /dev/input/js0
+ m_initialized = false;
+ close(m_fd);
+ return;
+ }
+
+ m_name = libevdev_get_name(m_dev);
+
+ // Controller buttons (and keyboard keys)
+ int num_buttons = 0;
+ for (int key = 0; key < KEY_MAX; key++)
+ if (libevdev_has_event_code(m_dev, EV_KEY, key))
+ AddInput(new Button(num_buttons++, key, m_dev));
+
+ // Absolute axis (thumbsticks)
+ int num_axis = 0;
+ for (int axis = 0; axis < 0x100; axis++)
+ if (libevdev_has_event_code(m_dev, EV_ABS, axis))
+ {
+ AddAnalogInputs(new Axis(num_axis, axis, false, m_dev),
+ new Axis(num_axis, axis, true, m_dev));
+ num_axis++;
+ }
+
+ // Force feedback
+ if (libevdev_has_event_code(m_dev, EV_FF, FF_PERIODIC))
+ {
+ for (auto type : {FF_SINE, FF_SQUARE, FF_TRIANGLE, FF_SAW_UP, FF_SAW_DOWN})
+ if (libevdev_has_event_code(m_dev, EV_FF, type))
+ AddOutput(new ForceFeedback(type, m_dev));
+ }
+ if (libevdev_has_event_code(m_dev, EV_FF, FF_RUMBLE))
+ {
+ AddOutput(new ForceFeedback(FF_RUMBLE, m_dev));
+ }
+
+ // TODO: Add leds as output devices
+
+ m_initialized = true;
+ m_interesting = num_axis >= 2 || num_buttons >= 8;
+}
+
+evdevDevice::~evdevDevice()
+{
+ if (m_initialized)
+ {
+ libevdev_free(m_dev);
+ close(m_fd);
+ }
+}
+
+void evdevDevice::UpdateInput()
+{
+ // Run through all evdev events
+ // libevdev will keep track of the actual controller state internally which can be queried
+ // later with libevdev_fetch_event_value()
+ input_event ev;
+ int rc = LIBEVDEV_READ_STATUS_SUCCESS;
+ do
+ {
+ if (rc == LIBEVDEV_READ_STATUS_SYNC)
+ rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
+ else
+ rc = libevdev_next_event(m_dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
+ } while (rc >= 0);
+}
+
+
+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(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_upper(upper), m_dev(dev)
+{
+ m_min = libevdev_get_abs_minimum(m_dev, m_code);
+ m_range = libevdev_get_abs_maximum(m_dev, m_code) + abs(m_min);
+}
+
+std::string evdevDevice::Axis::GetName() const
+{
+ return "Axis " + std::to_string(m_index) + (m_upper ? "+" : "-");
+}
+
+ControlState evdevDevice::Axis::GetState() const
+{
+ int value = 0;
+ libevdev_fetch_event_value(m_dev, EV_ABS, m_code, &value);
+
+ // Value from 0.0 to 1.0
+ ControlState fvalue = double(value - m_min) / double(m_range);
+
+ // Split into two axis, each covering half the range from 0.0 to 1.0
+ if (m_upper)
+ return std::max(0.0, fvalue - 0.5) * 2.0;
+ else
+ return (0.5 - std::min(0.5, fvalue)) * 2.0;
+}
+
+std::string evdevDevice::ForceFeedback::GetName() const
+{
+ // We have some default names.
+ switch (m_type)
+ {
+ case FF_SINE:
+ return "Sine";
+ case FF_TRIANGLE:
+ return "Triangle";
+ case FF_SQUARE:
+ return "Square";
+ case FF_RUMBLE:
+ return "LeftRight";
+ default:
+ {
+ const char* name = libevdev_event_code_get_name(EV_FF, m_type);
+ if (name)
+ return std::string(name);
+ return "Unknown";
+ }
+ }
+}
+
+void evdevDevice::ForceFeedback::SetState(ControlState state)
+{
+ // libevdev doesn't have nice helpers for forcefeedback
+ // we will use the file descriptors directly.
+
+ if (m_id != -1) // delete the previous effect (which also stops it)
+ {
+ ioctl(m_fd, EVIOCRMFF, m_id);
+ m_id = -1;
+ }
+
+ if (state > 0) // Upload and start an effect.
+ {
+ ff_effect effect;
+
+ effect.id = -1;
+ effect.direction = 0; // down
+ effect.replay.length = 500; // 500ms
+ effect.replay.delay = 0;
+ effect.trigger.button = 0; // don't trigger on button press
+ effect.trigger.interval = 0;
+
+ // This is the the interface that XInput uses, with 2 motors of differing sizes/frequencies that
+ // are controlled seperatally
+ if (m_type == FF_RUMBLE)
+ {
+ effect.type = FF_RUMBLE;
+ // max ranges tuned to 'feel' similar in magnitude to triangle/sine on xbox360 controller
+ effect.u.rumble.strong_magnitude = u16(state * 0x4000);
+ effect.u.rumble.weak_magnitude = u16(state * 0xFFFF);
+ }
+ else // FF_PERIODIC, a more generic interface.
+ {
+ effect.type = FF_PERIODIC;
+ effect.u.periodic.waveform = m_type;
+ effect.u.periodic.phase = 0x7fff; // 180 degrees
+ effect.u.periodic.offset = 0;
+ effect.u.periodic.period = 10;
+ effect.u.periodic.magnitude = s16(state * 0x7FFF);
+ effect.u.periodic.envelope.attack_length = 0; // no attack
+ effect.u.periodic.envelope.attack_level = 0;
+ effect.u.periodic.envelope.fade_length = 0;
+ effect.u.periodic.envelope.fade_level = 0;
+ }
+
+ ioctl(m_fd, EVIOCSFF, &effect);
+ m_id = effect.id;
+
+ input_event play;
+ play.type = EV_FF;
+ play.code = m_id;
+ play.value = 1;
+
+ write(m_fd, (const void*) &play, sizeof(play));
+ }
+}
+
+evdevDevice::ForceFeedback::~ForceFeedback()
+{
+ // delete the uploaded effect, so we don't leak it.
+ if (m_id != -1)
+ {
+ ioctl(m_fd, EVIOCRMFF, m_id);
+ }
+}
+
+}
+}
diff --git a/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
new file mode 100644
index 0000000000..5b3c23a466
--- /dev/null
+++ b/Source/Core/InputCommon/ControllerInterface/evdev/evdev.h
@@ -0,0 +1,87 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <libevdev/libevdev.h>
+
+#include "InputCommon/ControllerInterface/Device.h"
+
+namespace ciface
+{
+namespace evdev
+{
+
+void Init(std::vector<Core::Device*>& devices);
+
+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;
+ const bool m_upper;
+ int m_range;
+ int m_min;
+ libevdev* m_dev;
+ };
+
+ class ForceFeedback : public Core::Device::Output
+ {
+ public:
+ std::string GetName() const override;
+ ForceFeedback(u16 type, libevdev* dev) : m_type(type), m_id(-1) { m_fd = libevdev_get_fd(dev); }
+ ~ForceFeedback();
+ void SetState(ControlState state) override;
+ private:
+ const u16 m_type;
+ int m_fd;
+ int m_id;
+ };
+
+public:
+ void UpdateInput() override;
+
+ evdevDevice(const std::string &devnode, int id);
+ ~evdevDevice();
+
+ std::string GetName() const override { return m_name; }
+ int GetId() const override { return m_id; }
+ std::string GetSource() const override { return "evdev"; }
+
+ bool IsInteresting() const { return m_initialized && m_interesting; }
+
+private:
+ const std::string m_devfile;
+ int m_fd;
+ libevdev* m_dev;
+ std::string m_name;
+ const int m_id;
+ bool m_initialized;
+ bool m_interesting;
+};
+
+}
+
+}