Linux: Gamepad support (using libevdev)
This commit is contained in:
parent
760011b66d
commit
bdbf830dd7
11 changed files with 6153 additions and 32 deletions
|
@ -55,32 +55,61 @@
|
||||||
Left = InteropEmu.GetKeyCode("Left Arrow"), Right = InteropEmu.GetKeyCode("Right Arrow")
|
Left = InteropEmu.GetKeyCode("Left Arrow"), Right = InteropEmu.GetKeyCode("Right Arrow")
|
||||||
};
|
};
|
||||||
|
|
||||||
for(int i = 0; i < 2; i++) {
|
if(Program.IsMono) {
|
||||||
string prefix = "Pad" + (i+1).ToString() + " ";
|
for(int i = 0; i < 2; i++) {
|
||||||
_xboxLayouts[i] = new KeyMappings() {
|
string prefix = "Pad" + (i+1).ToString() + " ";
|
||||||
A = InteropEmu.GetKeyCode(prefix + "A"), B = InteropEmu.GetKeyCode(prefix + "X"),
|
_xboxLayouts[i] = new KeyMappings() {
|
||||||
TurboA = InteropEmu.GetKeyCode(prefix + "B"), TurboB = InteropEmu.GetKeyCode(prefix + "Y"),
|
A = InteropEmu.GetKeyCode(prefix + "A"), B = InteropEmu.GetKeyCode(prefix + "X"),
|
||||||
Select = InteropEmu.GetKeyCode(prefix + "Back"), Start = InteropEmu.GetKeyCode(prefix + "Start"),
|
TurboA = InteropEmu.GetKeyCode(prefix + "B"), TurboB = InteropEmu.GetKeyCode(prefix + "Y"),
|
||||||
Up = InteropEmu.GetKeyCode(prefix + "Up"), Down = InteropEmu.GetKeyCode(prefix + "Down"),
|
Select = InteropEmu.GetKeyCode(prefix + "Select"), Start = InteropEmu.GetKeyCode(prefix + "Start"),
|
||||||
Left = InteropEmu.GetKeyCode(prefix + "Left"), Right = InteropEmu.GetKeyCode(prefix + "Right")
|
Up = InteropEmu.GetKeyCode(prefix + "Up"), Down = InteropEmu.GetKeyCode(prefix + "Down"),
|
||||||
};
|
Left = InteropEmu.GetKeyCode(prefix + "Left"), Right = InteropEmu.GetKeyCode(prefix + "Right")
|
||||||
|
};
|
||||||
|
|
||||||
prefix = "Joy" + (i+1).ToString() + " ";
|
_ps4Layouts[i] = new KeyMappings() {
|
||||||
_ps4Layouts[i] = new KeyMappings() {
|
A = InteropEmu.GetKeyCode(prefix + "B"), B = InteropEmu.GetKeyCode(prefix + "A"),
|
||||||
A = InteropEmu.GetKeyCode(prefix + "But2"), B = InteropEmu.GetKeyCode(prefix + "But1"),
|
TurboA = InteropEmu.GetKeyCode(prefix + "C"), TurboB = InteropEmu.GetKeyCode(prefix + "X"),
|
||||||
TurboA = InteropEmu.GetKeyCode(prefix + "But3"), TurboB = InteropEmu.GetKeyCode(prefix + "But4"),
|
Select = InteropEmu.GetKeyCode(prefix + "L2"), Start = InteropEmu.GetKeyCode(prefix + "R2"),
|
||||||
Select = InteropEmu.GetKeyCode(prefix + "But9"), Start = InteropEmu.GetKeyCode(prefix + "But10"),
|
Up = InteropEmu.GetKeyCode(prefix + "Up"), Down = InteropEmu.GetKeyCode(prefix + "Down"),
|
||||||
Up = InteropEmu.GetKeyCode(prefix + "DPad Up"), Down = InteropEmu.GetKeyCode(prefix + "DPad Down"),
|
Left = InteropEmu.GetKeyCode(prefix + "Left"), Right = InteropEmu.GetKeyCode(prefix + "Right")
|
||||||
Left = InteropEmu.GetKeyCode(prefix + "DPad Left"), Right = InteropEmu.GetKeyCode(prefix + "DPad Right")
|
};
|
||||||
};
|
|
||||||
|
|
||||||
_snes30Layouts[i] = new KeyMappings() {
|
_snes30Layouts[i] = new KeyMappings() {
|
||||||
A = InteropEmu.GetKeyCode(prefix + "But2"), B = InteropEmu.GetKeyCode(prefix + "But5"),
|
A = InteropEmu.GetKeyCode(prefix + "Thumb"), B = InteropEmu.GetKeyCode(prefix + "Top2"),
|
||||||
TurboA = InteropEmu.GetKeyCode(prefix + "But1"), TurboB = InteropEmu.GetKeyCode(prefix + "But4"),
|
TurboA = InteropEmu.GetKeyCode(prefix + "Trigger"), TurboB = InteropEmu.GetKeyCode(prefix + "Top"),
|
||||||
Select = InteropEmu.GetKeyCode(prefix + "But11"), Start = InteropEmu.GetKeyCode(prefix + "But12"),
|
Select = InteropEmu.GetKeyCode(prefix + "Base5"), Start = InteropEmu.GetKeyCode(prefix + "Base6"),
|
||||||
Up = InteropEmu.GetKeyCode(prefix + "Y+"), Down = InteropEmu.GetKeyCode(prefix + "Y-"),
|
Up = InteropEmu.GetKeyCode(prefix + "Y-"), Down = InteropEmu.GetKeyCode(prefix + "Y+"),
|
||||||
Left = InteropEmu.GetKeyCode(prefix + "X-"), Right = InteropEmu.GetKeyCode(prefix + "X+")
|
Left = InteropEmu.GetKeyCode(prefix + "X-"), Right = InteropEmu.GetKeyCode(prefix + "X+")
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < 2; i++) {
|
||||||
|
string prefix = "Pad" + (i+1).ToString() + " ";
|
||||||
|
_xboxLayouts[i] = new KeyMappings() {
|
||||||
|
A = InteropEmu.GetKeyCode(prefix + "A"), B = InteropEmu.GetKeyCode(prefix + "X"),
|
||||||
|
TurboA = InteropEmu.GetKeyCode(prefix + "B"), TurboB = InteropEmu.GetKeyCode(prefix + "Y"),
|
||||||
|
Select = InteropEmu.GetKeyCode(prefix + "Back"), Start = InteropEmu.GetKeyCode(prefix + "Start"),
|
||||||
|
Up = InteropEmu.GetKeyCode(prefix + "Up"), Down = InteropEmu.GetKeyCode(prefix + "Down"),
|
||||||
|
Left = InteropEmu.GetKeyCode(prefix + "Left"), Right = InteropEmu.GetKeyCode(prefix + "Right")
|
||||||
|
};
|
||||||
|
|
||||||
|
prefix = "Joy" + (i+1).ToString() + " ";
|
||||||
|
_ps4Layouts[i] = new KeyMappings() {
|
||||||
|
A = InteropEmu.GetKeyCode(prefix + "But2"), B = InteropEmu.GetKeyCode(prefix + "But1"),
|
||||||
|
TurboA = InteropEmu.GetKeyCode(prefix + "But3"), TurboB = InteropEmu.GetKeyCode(prefix + "But4"),
|
||||||
|
Select = InteropEmu.GetKeyCode(prefix + "But9"), Start = InteropEmu.GetKeyCode(prefix + "But10"),
|
||||||
|
Up = InteropEmu.GetKeyCode(prefix + "DPad Up"), Down = InteropEmu.GetKeyCode(prefix + "DPad Down"),
|
||||||
|
Left = InteropEmu.GetKeyCode(prefix + "DPad Left"), Right = InteropEmu.GetKeyCode(prefix + "DPad Right")
|
||||||
|
};
|
||||||
|
|
||||||
|
_snes30Layouts[i] = new KeyMappings() {
|
||||||
|
A = InteropEmu.GetKeyCode(prefix + "But2"), B = InteropEmu.GetKeyCode(prefix + "But5"),
|
||||||
|
TurboA = InteropEmu.GetKeyCode(prefix + "But1"), TurboB = InteropEmu.GetKeyCode(prefix + "But4"),
|
||||||
|
Select = InteropEmu.GetKeyCode(prefix + "But11"), Start = InteropEmu.GetKeyCode(prefix + "But12"),
|
||||||
|
Up = InteropEmu.GetKeyCode(prefix + "Y+"), Down = InteropEmu.GetKeyCode(prefix + "Y-"),
|
||||||
|
Left = InteropEmu.GetKeyCode(prefix + "X-"), Right = InteropEmu.GetKeyCode(prefix + "X+")
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
215
Linux/LinuxGameController.cpp
Normal file
215
Linux/LinuxGameController.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
#include "../Core/MessageManager.h"
|
||||||
|
#include "LinuxGameController.h"
|
||||||
|
#include "libevdev/libevdev.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
std::shared_ptr<LinuxGameController> LinuxGameController::GetController(int deviceID)
|
||||||
|
{
|
||||||
|
int fd = open(("/dev/input/event" + std::to_string(deviceID)).c_str(), O_RDONLY | O_NONBLOCK);
|
||||||
|
if(fd < 0) {
|
||||||
|
//fprintf(stderr, "error: %d %s\n", errno, strerror(errno));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
libevdev* device = nullptr;
|
||||||
|
int rc = libevdev_new_from_fd(fd, &device);
|
||||||
|
if(rc < 0) {
|
||||||
|
//fprintf(stderr, "error: %d %s\n", -rc, strerror(-rc));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(libevdev_has_event_type(device, EV_KEY) && libevdev_has_event_code(device, EV_KEY, BTN_GAMEPAD) ||
|
||||||
|
libevdev_has_event_type(device, EV_ABS) && libevdev_has_event_code(device, EV_ABS, ABS_X)) {
|
||||||
|
MessageManager::Log(std::string("[Input Connected] Name: ") + libevdev_get_name(device) + " Vendor: " + std::to_string(libevdev_get_id_vendor(device)) + " Product: " + std::to_string(libevdev_get_id_product(device)));
|
||||||
|
return std::shared_ptr<LinuxGameController>(new LinuxGameController(deviceID, fd, device));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxGameController::LinuxGameController(int deviceID, int fileDescriptor, libevdev* device)
|
||||||
|
{
|
||||||
|
_deviceID = deviceID;
|
||||||
|
_stopFlag = false;
|
||||||
|
_device = device;
|
||||||
|
_fd = fileDescriptor;
|
||||||
|
memset(_axisDefaultValue, 0, sizeof(_axisDefaultValue));
|
||||||
|
|
||||||
|
_eventThread = std::thread([=]() {
|
||||||
|
int rc;
|
||||||
|
bool calibrate = true;
|
||||||
|
|
||||||
|
do {
|
||||||
|
fd_set readSet;
|
||||||
|
FD_ZERO(&readSet);
|
||||||
|
FD_SET(_fd, &readSet);
|
||||||
|
|
||||||
|
//Timeout after 0.1 seconds (to allow thread to be terminated quickly)
|
||||||
|
timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 100000;
|
||||||
|
|
||||||
|
if(rc = select((int)_fd+1, &readSet, nullptr, nullptr, &timeout)) {
|
||||||
|
do {
|
||||||
|
struct input_event ev;
|
||||||
|
rc = libevdev_next_event(_device, LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||||
|
if(rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||||
|
while (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||||
|
rc = libevdev_next_event(_device, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||||
|
}
|
||||||
|
} else if(rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||||
|
//print_event(&ev);
|
||||||
|
}
|
||||||
|
} while(rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rc != LIBEVDEV_READ_STATUS_SYNC && rc != LIBEVDEV_READ_STATUS_SUCCESS && rc != -EAGAIN && rc != EWOULDBLOCK) {
|
||||||
|
//Device was disconnected
|
||||||
|
MessageManager::Log("[Input Device] Disconnected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(calibrate) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(100));
|
||||||
|
Calibrate();
|
||||||
|
calibrate = false;
|
||||||
|
}
|
||||||
|
} while(!_stopFlag);
|
||||||
|
|
||||||
|
_disconnected = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LinuxGameController::~LinuxGameController()
|
||||||
|
{
|
||||||
|
_stopFlag = true;
|
||||||
|
_eventThread.join();
|
||||||
|
|
||||||
|
libevdev_free(_device);
|
||||||
|
close(_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinuxGameController::Calibrate()
|
||||||
|
{
|
||||||
|
int axes[14] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y, ABS_HAT3X, ABS_HAT3Y };
|
||||||
|
for(int axis : axes) {
|
||||||
|
_axisDefaultValue[axis] = libevdev_get_event_value(_device, EV_ABS, axis);
|
||||||
|
//std::cout << "center values: " << std::to_string(_axisDefaultValue[axis]) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinuxGameController::CheckAxis(unsigned int code, bool forPositive)
|
||||||
|
{
|
||||||
|
int deadZoneNegative = (_axisDefaultValue[code] - libevdev_get_abs_minimum(_device, code)) * 0.225;
|
||||||
|
int deadZonePositive = (libevdev_get_abs_maximum(_device, code) - _axisDefaultValue[code]) * 0.225;
|
||||||
|
|
||||||
|
if(forPositive) {
|
||||||
|
return libevdev_get_event_value(_device, EV_ABS, code) - _axisDefaultValue[code] > deadZonePositive;
|
||||||
|
} else {
|
||||||
|
return libevdev_get_event_value(_device, EV_ABS, code) - _axisDefaultValue[code] < -deadZoneNegative;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinuxGameController::IsButtonPressed(int buttonNumber)
|
||||||
|
{
|
||||||
|
switch(buttonNumber) {
|
||||||
|
case 0: return libevdev_get_event_value(_device, EV_KEY, BTN_A) == 1;
|
||||||
|
case 1: return libevdev_get_event_value(_device, EV_KEY, BTN_B) == 1;
|
||||||
|
case 2: return libevdev_get_event_value(_device, EV_KEY, BTN_C) == 1;
|
||||||
|
case 3: return libevdev_get_event_value(_device, EV_KEY, BTN_X) == 1;
|
||||||
|
case 4: return libevdev_get_event_value(_device, EV_KEY, BTN_Y) == 1;
|
||||||
|
case 5: return libevdev_get_event_value(_device, EV_KEY, BTN_Z) == 1;
|
||||||
|
case 6: return libevdev_get_event_value(_device, EV_KEY, BTN_TL) == 1;
|
||||||
|
case 7: return libevdev_get_event_value(_device, EV_KEY, BTN_TR) == 1;
|
||||||
|
case 8: return libevdev_get_event_value(_device, EV_KEY, BTN_TL2) == 1;
|
||||||
|
case 9: return libevdev_get_event_value(_device, EV_KEY, BTN_TR2) == 1;
|
||||||
|
case 10: return libevdev_get_event_value(_device, EV_KEY, BTN_SELECT) == 1;
|
||||||
|
case 11: return libevdev_get_event_value(_device, EV_KEY, BTN_START) == 1;
|
||||||
|
case 12: return libevdev_get_event_value(_device, EV_KEY, BTN_THUMBL) == 1;
|
||||||
|
case 13: return libevdev_get_event_value(_device, EV_KEY, BTN_THUMBR) == 1;
|
||||||
|
|
||||||
|
case 14: return CheckAxis(ABS_X, true);
|
||||||
|
case 15: return CheckAxis(ABS_X, false);
|
||||||
|
case 16: return CheckAxis(ABS_Y, true);
|
||||||
|
case 17: return CheckAxis(ABS_Y, false);
|
||||||
|
case 18: return CheckAxis(ABS_Z, true);
|
||||||
|
case 19: return CheckAxis(ABS_Z, false);
|
||||||
|
case 20: return CheckAxis(ABS_RX, true);
|
||||||
|
case 21: return CheckAxis(ABS_RX, false);
|
||||||
|
case 22: return CheckAxis(ABS_RY, true);
|
||||||
|
case 23: return CheckAxis(ABS_RY, false);
|
||||||
|
case 24: return CheckAxis(ABS_RZ, true);
|
||||||
|
case 25: return CheckAxis(ABS_RZ, false);
|
||||||
|
|
||||||
|
case 26: return CheckAxis(ABS_HAT0X, true);
|
||||||
|
case 27: return CheckAxis(ABS_HAT0X, false);
|
||||||
|
case 28: return CheckAxis(ABS_HAT0Y, true);
|
||||||
|
case 29: return CheckAxis(ABS_HAT0Y, false);
|
||||||
|
case 30: return CheckAxis(ABS_HAT1X, true);
|
||||||
|
case 31: return CheckAxis(ABS_HAT1X, false);
|
||||||
|
case 32: return CheckAxis(ABS_HAT1Y, true);
|
||||||
|
case 33: return CheckAxis(ABS_HAT1Y, false);
|
||||||
|
case 34: return CheckAxis(ABS_HAT2X, true);
|
||||||
|
case 35: return CheckAxis(ABS_HAT2X, false);
|
||||||
|
case 36: return CheckAxis(ABS_HAT2Y, true);
|
||||||
|
case 37: return CheckAxis(ABS_HAT2Y, false);
|
||||||
|
case 38: return CheckAxis(ABS_HAT3X, true);
|
||||||
|
case 39: return CheckAxis(ABS_HAT3X, false);
|
||||||
|
case 40: return CheckAxis(ABS_HAT3Y, true);
|
||||||
|
case 41: return CheckAxis(ABS_HAT3Y, false);
|
||||||
|
|
||||||
|
case 42: return libevdev_get_event_value(_device, EV_KEY, BTN_TRIGGER) == 1;
|
||||||
|
case 43: return libevdev_get_event_value(_device, EV_KEY, BTN_THUMB) == 1;
|
||||||
|
case 44: return libevdev_get_event_value(_device, EV_KEY, BTN_THUMB2) == 1;
|
||||||
|
case 45: return libevdev_get_event_value(_device, EV_KEY, BTN_TOP) == 1;
|
||||||
|
case 46: return libevdev_get_event_value(_device, EV_KEY, BTN_TOP2) == 1;
|
||||||
|
case 47: return libevdev_get_event_value(_device, EV_KEY, BTN_PINKIE) == 1;
|
||||||
|
case 48: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE) == 1;
|
||||||
|
case 49: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE2) == 1;
|
||||||
|
case 50: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE3) == 1;
|
||||||
|
case 51: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE4) == 1;
|
||||||
|
case 52: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE5) == 1;
|
||||||
|
case 53: return libevdev_get_event_value(_device, EV_KEY, BTN_BASE6) == 1;
|
||||||
|
case 54: return libevdev_get_event_value(_device, EV_KEY, BTN_DEAD) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LinuxGameController::IsDisconnected()
|
||||||
|
{
|
||||||
|
return _disconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LinuxGameController::GetDeviceID()
|
||||||
|
{
|
||||||
|
return _deviceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
static int print_event(struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (ev->type == EV_SYN)
|
||||||
|
printf("Event: time %ld.%06ld, ++++++++++++++++++++ %s +++++++++++++++\n",
|
||||||
|
ev->time.tv_sec,
|
||||||
|
ev->time.tv_usec,
|
||||||
|
libevdev_event_type_get_name(ev->type));
|
||||||
|
else
|
||||||
|
printf("Event: time %ld.%06ld, type %d (%s), code %d (%s), value %d\n",
|
||||||
|
ev->time.tv_sec,
|
||||||
|
ev->time.tv_usec,
|
||||||
|
ev->type,
|
||||||
|
libevdev_event_type_get_name(ev->type),
|
||||||
|
ev->code,
|
||||||
|
libevdev_event_code_get_name(ev->type, ev->code),
|
||||||
|
ev->value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
30
Linux/LinuxGameController.h
Normal file
30
Linux/LinuxGameController.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#pragma once
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
struct libevdev;
|
||||||
|
|
||||||
|
class LinuxGameController
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int _fd = -1;
|
||||||
|
int _deviceID = -1;
|
||||||
|
libevdev *_device = nullptr;
|
||||||
|
bool _disconnected = false;
|
||||||
|
std::thread _eventThread;
|
||||||
|
std::atomic<bool> _stopFlag;
|
||||||
|
int _axisDefaultValue[0x100];
|
||||||
|
|
||||||
|
LinuxGameController(int deviceID, int fileDescriptor, libevdev *device);
|
||||||
|
bool CheckAxis(unsigned int code, bool forPositive);
|
||||||
|
void Calibrate();
|
||||||
|
|
||||||
|
public:
|
||||||
|
~LinuxGameController();
|
||||||
|
|
||||||
|
static std::shared_ptr<LinuxGameController> GetController(int deviceID);
|
||||||
|
|
||||||
|
bool IsDisconnected();
|
||||||
|
int GetDeviceID();
|
||||||
|
bool IsButtonPressed(int buttonNumber);
|
||||||
|
};
|
|
@ -1,5 +1,8 @@
|
||||||
#include "LinuxKeyManager.h"
|
#include <algorithm>
|
||||||
|
#include "LinuxKeyManager.h"
|
||||||
|
#include "LinuxGameController.h"
|
||||||
#include "../Core/ControlManager.h"
|
#include "../Core/ControlManager.h"
|
||||||
|
#include "../Core/Console.h"
|
||||||
|
|
||||||
static vector<KeyDefinition> _keyDefinitions = {
|
static vector<KeyDefinition> _keyDefinitions = {
|
||||||
{ "", 9, "Escape", "" },
|
{ "", 9, "Escape", "" },
|
||||||
|
@ -228,14 +231,45 @@ LinuxKeyManager::LinuxKeyManager()
|
||||||
{
|
{
|
||||||
ResetKeyState();
|
ResetKeyState();
|
||||||
|
|
||||||
|
vector<string> buttonNames = {
|
||||||
|
"A", "B", "C", "X", "Y", "Z", "L1", "R1", "L2", "R2", "Select", "Start", "L3", "R3",
|
||||||
|
"X+", "X-", "Y+", "Y-", "Z+", "Z-",
|
||||||
|
"X2+", "X2-", "Y2+", "Y2-", "Z2+", "Z2-",
|
||||||
|
"Right", "Left", "Down", "Up",
|
||||||
|
"Right 2", "Left 2", "Down 2", "Up 2",
|
||||||
|
"Right 3", "Left 3", "Down 3", "Up 3",
|
||||||
|
"Right 4", "Left 4", "Down 4", "Up 4",
|
||||||
|
"Trigger", "Thumb", "Thumb2", "Top", "Top2",
|
||||||
|
"Pinkie", "Base", "Base2", "Base3", "Base4",
|
||||||
|
"Base5", "Base6", "Dead"
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int i = 0; i < 20; i++) {
|
||||||
|
for(int j = 0; j < (int)buttonNames.size(); j++) {
|
||||||
|
_keyDefinitions.push_back({ "", (uint32_t)(0x10000 + i * 0x100 + j), "Pad" + std::to_string(i + 1) + " " + buttonNames[j] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(KeyDefinition &keyDef : _keyDefinitions) {
|
for(KeyDefinition &keyDef : _keyDefinitions) {
|
||||||
_keyNames[keyDef.keyCode] = keyDef.description;
|
_keyNames[keyDef.keyCode] = keyDef.description;
|
||||||
_keyCodes[keyDef.description] = keyDef.keyCode;
|
_keyCodes[keyDef.description] = keyDef.keyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 30; i++) {
|
||||||
|
std::shared_ptr<LinuxGameController> controller = LinuxGameController::GetController(i);
|
||||||
|
if(controller) {
|
||||||
|
_controllers.push_back(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_stopUpdateDeviceThread = false;
|
||||||
|
StartUpdateDeviceThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
LinuxKeyManager::~LinuxKeyManager()
|
LinuxKeyManager::~LinuxKeyManager()
|
||||||
{
|
{
|
||||||
|
_stopUpdateDeviceThread = true;
|
||||||
|
_updateDeviceThread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxKeyManager::RefreshState()
|
void LinuxKeyManager::RefreshState()
|
||||||
|
@ -246,7 +280,13 @@ void LinuxKeyManager::RefreshState()
|
||||||
|
|
||||||
bool LinuxKeyManager::IsKeyPressed(uint32_t key)
|
bool LinuxKeyManager::IsKeyPressed(uint32_t key)
|
||||||
{
|
{
|
||||||
if(key < 0x200) {
|
if(key >= 0x10000) {
|
||||||
|
uint8_t gamepadPort = (key - 0x10000) / 0x100;
|
||||||
|
uint8_t gamepadButton = (key - 0x10000) % 0x100;
|
||||||
|
if(_controllers.size() > gamepadPort) {
|
||||||
|
return _controllers[gamepadPort]->IsButtonPressed(gamepadButton);
|
||||||
|
}
|
||||||
|
} else if(key < 0x200) {
|
||||||
return _keyState[key & 0xFF] != 0;
|
return _keyState[key & 0xFF] != 0;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -265,6 +305,14 @@ bool LinuxKeyManager::IsMouseButtonPressed(MouseButton button)
|
||||||
|
|
||||||
uint32_t LinuxKeyManager::GetPressedKey()
|
uint32_t LinuxKeyManager::GetPressedKey()
|
||||||
{
|
{
|
||||||
|
for(size_t i = 0; i < _controllers.size(); i++) {
|
||||||
|
for(int j = 0; j <= 54; j++) {
|
||||||
|
if(_controllers[i]->IsButtonPressed(j)) {
|
||||||
|
return 0x10000 + i * 0x100 + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 0x200; i++) {
|
for(int i = 0; i < 0x200; i++) {
|
||||||
if(_keyState[i]) {
|
if(_keyState[i]) {
|
||||||
return i;
|
return i;
|
||||||
|
@ -275,7 +323,7 @@ uint32_t LinuxKeyManager::GetPressedKey()
|
||||||
|
|
||||||
string LinuxKeyManager::GetKeyName(uint32_t key)
|
string LinuxKeyManager::GetKeyName(uint32_t key)
|
||||||
{
|
{
|
||||||
auto keyDef = _keyNames.find(key & 0xFF);
|
auto keyDef = _keyNames.find(key);
|
||||||
if(keyDef != _keyNames.end()) {
|
if(keyDef != _keyNames.end()) {
|
||||||
return keyDef->second;
|
return keyDef->second;
|
||||||
}
|
}
|
||||||
|
@ -297,6 +345,47 @@ void LinuxKeyManager::UpdateDevices()
|
||||||
//Only needed to detect newly plugged in devices
|
//Only needed to detect newly plugged in devices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LinuxKeyManager::StartUpdateDeviceThread()
|
||||||
|
{
|
||||||
|
_updateDeviceThread = std::thread([=]() {
|
||||||
|
while(!_stopUpdateDeviceThread) {
|
||||||
|
//Check for newly plugged in controllers every 2 secs
|
||||||
|
vector<int> indexesToRemove;
|
||||||
|
vector<int> connectedIDs;
|
||||||
|
std::vector<shared_ptr<LinuxGameController>> controllersToAdd;
|
||||||
|
for(int i = _controllers.size() - 1; i >= 0; i--) {
|
||||||
|
if(_controllers[i]->IsDisconnected()) {
|
||||||
|
indexesToRemove.push_back(i);
|
||||||
|
} else {
|
||||||
|
connectedIDs.push_back(_controllers[i]->GetDeviceID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 30; i++) {
|
||||||
|
if(std::find(connectedIDs.begin(), connectedIDs.end(), i) == connectedIDs.end()) {
|
||||||
|
std::shared_ptr<LinuxGameController> controller = LinuxGameController::GetController(i);
|
||||||
|
if(controller) {
|
||||||
|
controllersToAdd.push_back(controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!indexesToRemove.empty() || !controllersToAdd.empty()) {
|
||||||
|
Console::Pause();
|
||||||
|
for(int index : indexesToRemove) {
|
||||||
|
_controllers.erase(_controllers.begin()+index);
|
||||||
|
}
|
||||||
|
for(std::shared_ptr<LinuxGameController> controller : controllersToAdd) {
|
||||||
|
_controllers.push_back(controller);
|
||||||
|
}
|
||||||
|
Console::Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(2000));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void LinuxKeyManager::SetKeyState(uint16_t scanCode, bool state)
|
void LinuxKeyManager::SetKeyState(uint16_t scanCode, bool state)
|
||||||
{
|
{
|
||||||
if(scanCode > 0x1FF) {
|
if(scanCode > 0x1FF) {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <thread>
|
||||||
#include "../Core/IKeyManager.h"
|
#include "../Core/IKeyManager.h"
|
||||||
|
|
||||||
|
class LinuxGameController;
|
||||||
|
|
||||||
struct KeyDefinition {
|
struct KeyDefinition {
|
||||||
string name;
|
string name;
|
||||||
uint32_t keyCode;
|
uint32_t keyCode;
|
||||||
|
@ -12,11 +16,17 @@ struct KeyDefinition {
|
||||||
class LinuxKeyManager : public IKeyManager
|
class LinuxKeyManager : public IKeyManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
std::vector<shared_ptr<LinuxGameController>> _controllers;
|
||||||
bool _keyState[0x200];
|
bool _keyState[0x200];
|
||||||
bool _mouseState[0x03];
|
bool _mouseState[0x03];
|
||||||
std::unordered_map<uint32_t, string> _keyNames;
|
std::unordered_map<uint32_t, string> _keyNames;
|
||||||
std::unordered_map<string, uint32_t> _keyCodes;
|
std::unordered_map<string, uint32_t> _keyCodes;
|
||||||
|
|
||||||
|
std::thread _updateDeviceThread;
|
||||||
|
atomic<bool> _stopUpdateDeviceThread;
|
||||||
|
|
||||||
|
void StartUpdateDeviceThread();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LinuxKeyManager();
|
LinuxKeyManager();
|
||||||
virtual ~LinuxKeyManager();
|
virtual ~LinuxKeyManager();
|
||||||
|
|
1425
Linux/libevdev/event-names.h
Normal file
1425
Linux/libevdev/event-names.h
Normal file
File diff suppressed because it is too large
Load diff
341
Linux/libevdev/libevdev-int.h
Executable file
341
Linux/libevdev/libevdev-int.h
Executable file
|
@ -0,0 +1,341 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBEVDEV_INT_H
|
||||||
|
#define LIBEVDEV_INT_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "libevdev.h"
|
||||||
|
#include "libevdev-util.h"
|
||||||
|
|
||||||
|
#define MAX_NAME 256
|
||||||
|
#define ABS_MT_MIN ABS_MT_SLOT
|
||||||
|
#define ABS_MT_MAX ABS_MT_TOOL_Y
|
||||||
|
#define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
|
||||||
|
#define LIBEVDEV_EXPORT __attribute__((visibility("default")))
|
||||||
|
#define ALIAS(_to) __attribute__((alias(#_to)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync state machine:
|
||||||
|
* default state: SYNC_NONE
|
||||||
|
*
|
||||||
|
* SYNC_NONE → SYN_DROPPED or forced sync → SYNC_NEEDED
|
||||||
|
* SYNC_NEEDED → libevdev_next_event(LIBEVDEV_READ_FLAG_SYNC) → SYNC_IN_PROGRESS
|
||||||
|
* SYNC_NEEDED → libevdev_next_event(LIBEVDEV_READ_FLAG_SYNC_NONE) → SYNC_NONE
|
||||||
|
* SYNC_IN_PROGRESS → libevdev_next_event(LIBEVDEV_READ_FLAG_SYNC_NONE) → SYNC_NONE
|
||||||
|
* SYNC_IN_PROGRESS → no sync events left → SYNC_NONE
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum SyncState {
|
||||||
|
SYNC_NONE,
|
||||||
|
SYNC_NEEDED,
|
||||||
|
SYNC_IN_PROGRESS,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mt_sync_state {
|
||||||
|
int code;
|
||||||
|
int val[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal only: log data used to send messages to the respective log
|
||||||
|
* handler. We re-use the same struct for a global and inside
|
||||||
|
* struct libevdev.
|
||||||
|
* For the global, device_handler is NULL, for per-device instance
|
||||||
|
* global_handler is NULL.
|
||||||
|
*/
|
||||||
|
struct logdata {
|
||||||
|
enum libevdev_log_priority priority; /** minimum logging priority */
|
||||||
|
libevdev_log_func_t global_handler; /** global handler function */
|
||||||
|
libevdev_device_log_func_t device_handler; /** per-device handler function */
|
||||||
|
void *userdata; /** user-defined data pointer */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libevdev {
|
||||||
|
int fd;
|
||||||
|
bool initialized;
|
||||||
|
char *name;
|
||||||
|
char *phys;
|
||||||
|
char *uniq;
|
||||||
|
struct input_id ids;
|
||||||
|
int driver_version;
|
||||||
|
unsigned long bits[NLONGS(EV_CNT)];
|
||||||
|
unsigned long props[NLONGS(INPUT_PROP_CNT)];
|
||||||
|
unsigned long key_bits[NLONGS(KEY_CNT)];
|
||||||
|
unsigned long rel_bits[NLONGS(REL_CNT)];
|
||||||
|
unsigned long abs_bits[NLONGS(ABS_CNT)];
|
||||||
|
unsigned long led_bits[NLONGS(LED_CNT)];
|
||||||
|
unsigned long msc_bits[NLONGS(MSC_CNT)];
|
||||||
|
unsigned long sw_bits[NLONGS(SW_CNT)];
|
||||||
|
unsigned long rep_bits[NLONGS(REP_CNT)]; /* convenience, always 1 */
|
||||||
|
unsigned long ff_bits[NLONGS(FF_CNT)];
|
||||||
|
unsigned long snd_bits[NLONGS(SND_CNT)];
|
||||||
|
unsigned long key_values[NLONGS(KEY_CNT)];
|
||||||
|
unsigned long led_values[NLONGS(LED_CNT)];
|
||||||
|
unsigned long sw_values[NLONGS(SW_CNT)];
|
||||||
|
struct input_absinfo abs_info[ABS_CNT];
|
||||||
|
int *mt_slot_vals; /* [num_slots * ABS_MT_CNT] */
|
||||||
|
int num_slots; /**< valid slots in mt_slot_vals */
|
||||||
|
int current_slot;
|
||||||
|
int rep_values[REP_CNT];
|
||||||
|
|
||||||
|
enum SyncState sync_state;
|
||||||
|
enum libevdev_grab_mode grabbed;
|
||||||
|
|
||||||
|
struct input_event *queue;
|
||||||
|
size_t queue_size; /**< size of queue in elements */
|
||||||
|
size_t queue_next; /**< next event index */
|
||||||
|
size_t queue_nsync; /**< number of sync events */
|
||||||
|
|
||||||
|
struct timeval last_event_time;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct mt_sync_state *mt_state;
|
||||||
|
size_t mt_state_sz; /* in bytes */
|
||||||
|
unsigned long *slot_update;
|
||||||
|
size_t slot_update_sz; /* in bytes */
|
||||||
|
unsigned long *tracking_id_changes;
|
||||||
|
size_t tracking_id_changes_sz; /* in bytes */
|
||||||
|
} mt_sync;
|
||||||
|
|
||||||
|
struct logdata log;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define log_msg_cond(dev, priority, ...) \
|
||||||
|
do { \
|
||||||
|
if (_libevdev_log_priority(dev) >= priority) \
|
||||||
|
_libevdev_log_msg(dev, priority, __FILE__, __LINE__, __func__, __VA_ARGS__); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define log_error(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_ERROR, __VA_ARGS__)
|
||||||
|
#define log_info(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_INFO, __VA_ARGS__)
|
||||||
|
#define log_dbg(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#define log_bug(dev, ...) log_msg_cond(dev, LIBEVDEV_LOG_ERROR, "BUG: "__VA_ARGS__)
|
||||||
|
|
||||||
|
extern void
|
||||||
|
_libevdev_log_msg(const struct libevdev *dev,
|
||||||
|
enum libevdev_log_priority priority,
|
||||||
|
const char *file, int line, const char *func,
|
||||||
|
const char *format, ...) LIBEVDEV_ATTRIBUTE_PRINTF(6, 7);
|
||||||
|
extern enum libevdev_log_priority
|
||||||
|
_libevdev_log_priority(const struct libevdev *dev);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a pointer to the next element in the queue, or NULL if the queue
|
||||||
|
* is full.
|
||||||
|
*/
|
||||||
|
static inline struct input_event*
|
||||||
|
queue_push(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next >= dev->queue_size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &dev->queue[dev->queue_next++];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ev to the last element in the queue, removing it from the queue.
|
||||||
|
*
|
||||||
|
* @return 0 on success, 1 if the queue is empty.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
queue_pop(struct libevdev *dev, struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
*ev = dev->queue[--dev->queue_next];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_peek(struct libevdev *dev, size_t idx, struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next == 0 || idx > dev->queue_next)
|
||||||
|
return 1;
|
||||||
|
*ev = dev->queue[idx];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shift the first n elements into ev and return the number of elements
|
||||||
|
* shifted.
|
||||||
|
* ev must be large enough to store n elements.
|
||||||
|
*
|
||||||
|
* @param ev The buffer to copy into, or NULL
|
||||||
|
* @return The number of elements in ev.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
queue_shift_multiple(struct libevdev *dev, size_t n, struct input_event *ev)
|
||||||
|
{
|
||||||
|
size_t remaining;
|
||||||
|
|
||||||
|
if (dev->queue_next == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
remaining = dev->queue_next;
|
||||||
|
n = min(n, remaining);
|
||||||
|
remaining -= n;
|
||||||
|
|
||||||
|
if (ev)
|
||||||
|
memcpy(ev, dev->queue, n * sizeof(*ev));
|
||||||
|
|
||||||
|
memmove(dev->queue, &dev->queue[n], remaining * sizeof(*dev->queue));
|
||||||
|
|
||||||
|
dev->queue_next = remaining;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ev to the first element in the queue, shifting everything else
|
||||||
|
* forward by one.
|
||||||
|
*
|
||||||
|
* @return 0 on success, 1 if the queue is empty.
|
||||||
|
*/
|
||||||
|
static inline int
|
||||||
|
queue_shift(struct libevdev *dev, struct input_event *ev)
|
||||||
|
{
|
||||||
|
return queue_shift_multiple(dev, 1, ev) == 1 ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_alloc(struct libevdev *dev, size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->queue = calloc(size, sizeof(struct input_event));
|
||||||
|
if (!dev->queue)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->queue_size = size;
|
||||||
|
dev->queue_next = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
queue_free(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
free(dev->queue);
|
||||||
|
dev->queue_size = 0;
|
||||||
|
dev->queue_next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
queue_num_elements(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return dev->queue_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
queue_size(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
return dev->queue_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
queue_num_free_elements(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
if (dev->queue_size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return dev->queue_size - dev->queue_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct input_event *
|
||||||
|
queue_next_element(struct libevdev *dev)
|
||||||
|
{
|
||||||
|
if (dev->queue_next == dev->queue_size)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &dev->queue[dev->queue_next];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
queue_set_num_elements(struct libevdev *dev, size_t nelem)
|
||||||
|
{
|
||||||
|
if (nelem > dev->queue_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
dev->queue_next = nelem;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define max_mask(uc, lc) \
|
||||||
|
case EV_##uc: \
|
||||||
|
*mask = dev->lc##_bits; \
|
||||||
|
max = libevdev_event_type_get_max(type); \
|
||||||
|
break;
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
type_to_mask_const(const struct libevdev *dev, unsigned int type, const unsigned long **mask)
|
||||||
|
{
|
||||||
|
int max;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
max_mask(ABS, abs);
|
||||||
|
max_mask(REL, rel);
|
||||||
|
max_mask(KEY, key);
|
||||||
|
max_mask(LED, led);
|
||||||
|
max_mask(MSC, msc);
|
||||||
|
max_mask(SW, sw);
|
||||||
|
max_mask(FF, ff);
|
||||||
|
max_mask(REP, rep);
|
||||||
|
max_mask(SND, snd);
|
||||||
|
default:
|
||||||
|
max = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
type_to_mask(struct libevdev *dev, unsigned int type, unsigned long **mask)
|
||||||
|
{
|
||||||
|
int max;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
max_mask(ABS, abs);
|
||||||
|
max_mask(REL, rel);
|
||||||
|
max_mask(KEY, key);
|
||||||
|
max_mask(LED, led);
|
||||||
|
max_mask(MSC, msc);
|
||||||
|
max_mask(SW, sw);
|
||||||
|
max_mask(FF, ff);
|
||||||
|
max_mask(REP, rep);
|
||||||
|
max_mask(SND, snd);
|
||||||
|
default:
|
||||||
|
max = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef max_mask
|
||||||
|
#endif
|
80
Linux/libevdev/libevdev-util.h
Executable file
80
Linux/libevdev/libevdev-util.h
Executable file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2013 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
* the above copyright notice appear in all copies and that both that copyright
|
||||||
|
* notice and this permission notice appear in supporting documentation, and
|
||||||
|
* that the name of the copyright holders not be used in advertising or
|
||||||
|
* publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission. The copyright holders make no representations
|
||||||
|
* about the suitability of this software for any purpose. It is provided "as
|
||||||
|
* is" without express or implied warranty.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||||
|
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||||
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||||
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||||
|
* OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UTIL_H_
|
||||||
|
#define _UTIL_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define LONG_BITS (sizeof(long) * 8)
|
||||||
|
#define NLONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
|
||||||
|
#define ARRAY_LENGTH(a) (sizeof(a) / (sizeof((a)[0])))
|
||||||
|
#define unlikely(x) (__builtin_expect(!!(x),0))
|
||||||
|
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#define min(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _b : _a; \
|
||||||
|
})
|
||||||
|
#define max(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline bool
|
||||||
|
startswith(const char *str, size_t len, const char *prefix, size_t plen)
|
||||||
|
{
|
||||||
|
return len >= plen && !strncmp(str, prefix, plen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
bit_is_set(const unsigned long *array, int bit)
|
||||||
|
{
|
||||||
|
return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_bit(unsigned long *array, int bit)
|
||||||
|
{
|
||||||
|
array[bit / LONG_BITS] |= (1LL << (bit % LONG_BITS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
clear_bit(unsigned long *array, int bit)
|
||||||
|
{
|
||||||
|
array[bit / LONG_BITS] &= ~(1LL << (bit % LONG_BITS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
set_bit_state(unsigned long *array, int bit, int state)
|
||||||
|
{
|
||||||
|
if (state)
|
||||||
|
set_bit(array, bit);
|
||||||
|
else
|
||||||
|
clear_bit(array, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
1722
Linux/libevdev/libevdev.c
Executable file
1722
Linux/libevdev/libevdev.c
Executable file
File diff suppressed because it is too large
Load diff
2177
Linux/libevdev/libevdev.h
Executable file
2177
Linux/libevdev/libevdev.h
Executable file
File diff suppressed because it is too large
Load diff
11
makefile
11
makefile
|
@ -6,13 +6,14 @@
|
||||||
COREOBJ=$(patsubst Core/%.cpp,Core/obj/%.o,$(wildcard Core/*.cpp))
|
COREOBJ=$(patsubst Core/%.cpp,Core/obj/%.o,$(wildcard Core/*.cpp))
|
||||||
UTILOBJ=$(patsubst Utilities/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/*.cpp)) $(patsubst Utilities/HQX/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/HQX/*.cpp)) $(patsubst Utilities/xBRZ/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/xBRZ/*.cpp)) $(patsubst Utilities/KreedSaiEagle/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/KreedSaiEagle/*.cpp)) $(patsubst Utilities/Scale2x/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/Scale2x/*.cpp))
|
UTILOBJ=$(patsubst Utilities/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/*.cpp)) $(patsubst Utilities/HQX/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/HQX/*.cpp)) $(patsubst Utilities/xBRZ/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/xBRZ/*.cpp)) $(patsubst Utilities/KreedSaiEagle/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/KreedSaiEagle/*.cpp)) $(patsubst Utilities/Scale2x/%.cpp,Utilities/obj/%.o,$(wildcard Utilities/Scale2x/*.cpp))
|
||||||
LINUXOBJ=$(patsubst Linux/%.cpp,Linux/obj/%.o,$(wildcard Linux/*.cpp))
|
LINUXOBJ=$(patsubst Linux/%.cpp,Linux/obj/%.o,$(wildcard Linux/*.cpp))
|
||||||
|
LIBEVDEVOBJ=$(patsubst Linux/libevdev/%.c,Linux/obj/%.o,$(wildcard Linux/libevdev/*.c))
|
||||||
SEVENZIPOBJ=$(patsubst SevenZip/%.c,SevenZip/obj/%.o,$(wildcard SevenZip/*.c))
|
SEVENZIPOBJ=$(patsubst SevenZip/%.c,SevenZip/obj/%.o,$(wildcard SevenZip/*.c))
|
||||||
|
|
||||||
CPPC=clang++
|
CPPC=clang++
|
||||||
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3
|
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3
|
||||||
|
|
||||||
CC=clang
|
CC=clang
|
||||||
7ZOPTIONS=-fPIC -Wall -O3
|
CCOPTIONS=-fPIC -Wall -O3
|
||||||
|
|
||||||
SHAREDLIB=libMesenCore.dll
|
SHAREDLIB=libMesenCore.dll
|
||||||
RELEASEFOLDER=bin/x64/Release
|
RELEASEFOLDER=bin/x64/Release
|
||||||
|
@ -42,7 +43,7 @@ testhelper: $(SHAREDLIB)
|
||||||
cd TestHelper/obj && $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -Wno-parentheses -Wno-switch -o testhelper ../*.cpp ../../InteropDLL/ConsoleWrapper.cpp -L ./ -lCore -lMesenLinux -lUtilities -lSevenZip -pthread -lSDL2 -lstdc++fs
|
cd TestHelper/obj && $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -Wno-parentheses -Wno-switch -o testhelper ../*.cpp ../../InteropDLL/ConsoleWrapper.cpp -L ./ -lCore -lMesenLinux -lUtilities -lSevenZip -pthread -lSDL2 -lstdc++fs
|
||||||
|
|
||||||
SevenZip/obj/%.o: SevenZip/%.c
|
SevenZip/obj/%.o: SevenZip/%.c
|
||||||
mkdir -p SevenZip/obj && cd SevenZip/obj && $(CC) $(7ZOPTIONS) -fpermissive -c $(patsubst SevenZip/%, ../%, $<)
|
mkdir -p SevenZip/obj && cd SevenZip/obj && $(CC) $(CCOPTIONS) -fpermissive -c $(patsubst SevenZip/%, ../%, $<)
|
||||||
Utilities/obj/%.o: Utilities/%.cpp
|
Utilities/obj/%.o: Utilities/%.cpp
|
||||||
mkdir -p Utilities/obj && cd Utilities/obj && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<)
|
mkdir -p Utilities/obj && cd Utilities/obj && $(CPPC) $(GCCOPTIONS) -c $(patsubst Utilities/%, ../%, $<)
|
||||||
Utilities/obj/%.o: Utilities/HQX/%.cpp
|
Utilities/obj/%.o: Utilities/HQX/%.cpp
|
||||||
|
@ -57,11 +58,13 @@ Core/obj/%.o: Core/%.cpp
|
||||||
mkdir -p Core/obj && cd Core/obj && $(CPPC) $(GCCOPTIONS) -Wno-parentheses -Wno-switch -c $(patsubst Core/%, ../%, $<)
|
mkdir -p Core/obj && cd Core/obj && $(CPPC) $(GCCOPTIONS) -Wno-parentheses -Wno-switch -c $(patsubst Core/%, ../%, $<)
|
||||||
Linux/obj/%.o: Linux/%.cpp
|
Linux/obj/%.o: Linux/%.cpp
|
||||||
mkdir -p Linux/obj && cd Linux/obj && $(CPPC) $(GCCOPTIONS) -Wno-parentheses -Wno-switch -c $(patsubst Linux/%, ../%, $<)
|
mkdir -p Linux/obj && cd Linux/obj && $(CPPC) $(GCCOPTIONS) -Wno-parentheses -Wno-switch -c $(patsubst Linux/%, ../%, $<)
|
||||||
|
Linux/obj/%.o: Linux/libevdev/%.c
|
||||||
|
mkdir -p Linux/obj && cd Linux/obj && $(CC) $(CCOPTIONS) -Wno-parentheses -Wno-switch -c $(patsubst Linux/%, ../%, $<)
|
||||||
|
|
||||||
$(SHAREDLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LINUXOBJ) InteropDLL/ConsoleWrapper.cpp InteropDLL/DebugWrapper.cpp
|
$(SHAREDLIB): $(SEVENZIPOBJ) $(UTILOBJ) $(COREOBJ) $(LIBEVDEVOBJ) $(LINUXOBJ) InteropDLL/ConsoleWrapper.cpp InteropDLL/DebugWrapper.cpp
|
||||||
mkdir -p InteropDLL/obj
|
mkdir -p InteropDLL/obj
|
||||||
ar -rcs InteropDLL/obj/libSevenZip.a $(SEVENZIPOBJ)
|
ar -rcs InteropDLL/obj/libSevenZip.a $(SEVENZIPOBJ)
|
||||||
ar -rcs InteropDLL/obj/libMesenLinux.a $(LINUXOBJ)
|
ar -rcs InteropDLL/obj/libMesenLinux.a $(LINUXOBJ) $(LIBEVDEVOBJ)
|
||||||
ar -rcs InteropDLL/obj/libUtilities.a $(UTILOBJ)
|
ar -rcs InteropDLL/obj/libUtilities.a $(UTILOBJ)
|
||||||
ar -rcs InteropDLL/obj/libCore.a $(COREOBJ)
|
ar -rcs InteropDLL/obj/libCore.a $(COREOBJ)
|
||||||
cd InteropDLL/obj && $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -Wno-parentheses -Wno-switch -shared -o $(SHAREDLIB) ../*.cpp -L . -lCore -lMesenLinux -lUtilities -lSevenZip -pthread -lSDL2 -lstdc++fs
|
cd InteropDLL/obj && $(CPPC) $(GCCOPTIONS) -Wl,-z,defs -Wno-parentheses -Wno-switch -shared -o $(SHAREDLIB) ../*.cpp -L . -lCore -lMesenLinux -lUtilities -lSevenZip -pthread -lSDL2 -lstdc++fs
|
||||||
|
|
Loading…
Add table
Reference in a new issue