Skip to content

Commit

Permalink
Added keyboard input detection
Browse files Browse the repository at this point in the history
Also, edited the LuaScript source to remove some irritating false errors when running WeJoy, and some other clean up which I do not remember.
  • Loading branch information
Vantskruv authored Aug 13, 2019
1 parent 2bf2e16 commit 882c4ba
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 21 deletions.
64 changes: 64 additions & 0 deletions CKeyboard.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "CKeyboard.h"
//#include <libudev.h>
//#include <stdio.h>
#include <string.h>
#include <unistd.h> //usleep
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>


CKeyboard::CKeyboard(std::string _eventPath)
{
eventPath = _eventPath;
fd = open(eventPath.c_str(), O_RDONLY);
if(fd == -1)
{
fprintf(stderr, "KEYBOARD: Cannot open %s: %s.\n", eventPath.c_str(), strerror(errno));
}
}

CKeyboard::~CKeyboard()
{
if(fd>-1) close(fd);
}

std::string CKeyboard::getEventPath()
{
return eventPath;
}

bool CKeyboard::isOpen()
{
if(fd>-1) return true;

return false;
}

bool CKeyboard::readEvent(CKeyboardEvent* _keyEvent)
{
/*
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
*/

if(fd<0) return false;

struct input_event ev;
ssize_t n;
n = read(fd, &ev, sizeof ev);
if(n == ((ssize_t) - 1) || n!= sizeof(ev)) return false;

if(ev.type == EV_KEY && ev.value>=0 && ev.value<=2 && ev.value!=2)
{
_keyEvent->isPressed = ev.value;
_keyEvent->code = ev.code;
//printf("%s 0x%04x (%d) %d\n", evval[ev.value], (int)ev.code, (int)ev.code, (ev.code == KEY_Q ? 1 : 0));
return true;
}

return false;
}
29 changes: 29 additions & 0 deletions CKeyboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#ifndef CKEYBOARD_HEADER
#define CKEYBOARD_HEADER

#include <string>


class CKeyboardEvent
{
public:
bool isPressed;
char code;
};

class CKeyboard
{
private:
int fd = -1;
std::string eventPath;

public:
std::string getEventPath();
bool isOpen();
bool readEvent(CKeyboardEvent*);

CKeyboard(std::string eventPath);
~CKeyboard();
};

#endif
2 changes: 0 additions & 2 deletions CVirtualJoy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ CVirtualJoy::CVirtualJoy(unsigned int _buttons, unsigned int _axes)
{
deviceid = static_deviceid;

std::cout << "Opening virtual device " << deviceid << ".\n";
//Get a device descriptor
fd = suinput_open();
if(fd<0)
Expand Down Expand Up @@ -42,7 +41,6 @@ CVirtualJoy::CVirtualJoy(unsigned int _buttons, unsigned int _axes)
}//if
axesData.resize(_axes, 0);

std::cout << "Creating virtual device " << deviceid << ".\n";
//Create and initialize the device
struct uinput_user_dev user_dev;
memset(&user_dev, 0, sizeof(struct uinput_user_dev));
Expand Down
2 changes: 0 additions & 2 deletions CVirtualKeyboard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

CVirtualKeyboard::CVirtualKeyboard()
{
std::cout << "Opening virtual keyboard device.\n";
//Get a device descriptor
fd = suinput_open();
if(fd<0)
Expand All @@ -26,7 +25,6 @@ CVirtualKeyboard::CVirtualKeyboard()
}//if


std::cout << "Creating virtual keyboard device.\n";
//Create and initialize the device
struct uinput_user_dev user_dev;
memset(&user_dev, 0, sizeof(struct uinput_user_dev));
Expand Down
15 changes: 15 additions & 0 deletions example.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ devices =
vendorid = 0x044f,
productid = 0x0404,
}

kbd0 = "/dev/input/by-id/usb-04d9_USB_Keyboard-event-kbd" -- keyboard device (try to find a suitable device by listing input devices by typing 'ls /dev/input/by-id/' )
kbd1 = "/dev/input/by-id/usb-Aqua_Computer_GmbH___Co._KG_aquaero_07538-20376-event-kbd" -- another keyboard device example
}

--Virtual devices to create, current limit is maximum 53 (0 to 52) buttons and 19 (0 to 18) axes. Note that not every button or axis is fully tested to work.
Expand Down Expand Up @@ -40,6 +43,18 @@ v_devices =
-- get_vjoy_button_status(vjoy, button)
-- get_vjoy_axis_status(vjoy, axis)

function kbd0_pressed(value)
if value == KEY_W then
send_button_event(0, 1, 1)
end
end

function kbd0_released(value)
if value == KEY_W then
send_button_event(0, 1, 0)
end
end


-- Send keyboard key 'a' when button 0 on device 1 is pressed, and release the key when button is released.
function d1_b0_event(value)
Expand Down
4 changes: 3 additions & 1 deletion global.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define GLOBAL_H

#include <vector>
#include "CKeyboard.h"
#include "joystick.h"
#include "CVirtualJoy.h"
#include "CVirtualKeyboard.h"
Expand All @@ -10,7 +11,8 @@ namespace GLOBAL
{
std::vector<Joystick*> joyList;
std::vector<CVirtualJoy*> vJoyList;
CVirtualKeyboard vKeyboard;
std::vector<CKeyboard*> kbdList;
CVirtualKeyboard* vKeyboard;
}

#endif
84 changes: 69 additions & 15 deletions main.cc
Original file line number Diff line number Diff line change
@@ -1,35 +1,64 @@
#include <unistd.h> //sleep
#include <thread> //thread
#include <mutex>

#include "LuaScript.h"
#include "global.h"
#include "CKeyboard.h"

bool bPoll = true;
void updateThread(LuaScript& lScript)
std::mutex mtx;

void updateThreadJoysticks(LuaScript& lScript)
{
//Sleep one second to give the X11 system time to adapt.
sleep(1);

JoystickEvent event;
while(bPoll)
for(unsigned int i=0; i<GLOBAL::joyList.size(); i++)
{
usleep(1000);
if(GLOBAL::joyList[i]->readJoy(&event))
{
if(event.isButton()) lScript.call_device_function("d" + std::to_string(i) + "_b" + std::to_string(event.number) + "_event", event.value);
else if(event.isAxis()) lScript.call_device_function("d" + std::to_string(i) + "_a" + std::to_string(event.number) + "_event", event.value);
}//if
}//for
{
usleep(1000);
for(unsigned int i=0; i<GLOBAL::joyList.size(); i++)
{
if(GLOBAL::joyList[i]->readJoy(&event))
{
mtx.lock();
if(event.isButton()) lScript.call_device_function("d" + std::to_string(i) + "_b" + std::to_string(event.number) + "_event", event.value);
else if(event.isAxis()) lScript.call_device_function("d" + std::to_string(i) + "_a" + std::to_string(event.number) + "_event", event.value);
mtx.unlock();
}//if

}//for
}//while
}

void updateThreadKeyboard(LuaScript& lScript)
{
sleep(1);

CKeyboardEvent kbdEvent;
while(bPoll)
{
usleep(1000);
for(unsigned int i=0; i<GLOBAL::kbdList.size(); i++)
{
if(GLOBAL::kbdList[i]->readEvent(&kbdEvent))
{
mtx.lock();
if(kbdEvent.isPressed) lScript.call_device_function("kbd" + std::to_string(i) + "_pressed", kbdEvent.code);
else lScript.call_device_function("kbd" + std::to_string(i) + "_released", kbdEvent.code);
mtx.unlock();
}//if
}//for
}//while
}

//Called from user via lua script
int l_send_keyboard_event(lua_State* L)
{
int type = lua_tonumber(L, 1);
int value = lua_tonumber(L, 2);
GLOBAL::vKeyboard.send_key_event(type, value);
GLOBAL::vKeyboard->send_key_event(type, value);
return 0;
}

Expand Down Expand Up @@ -157,7 +186,7 @@ bool populate_devices(LuaScript& lScript)
//Populate the list of found joysticks
for(unsigned int i=0; i<dList.size(); i++)
{
Joystick* cJoy = new Joystick(dList[i][0], dList[i][1], GLOBAL::joyList);
Joystick* cJoy = new Joystick(dList[i][0], dList[i][1], GLOBAL::joyList);
if(!cJoy->isFound())
{
std::cout << "WARNING: Joystick " << std::hex << dList[i][0] << ":" << std::hex << dList[i][1] << " is not found.\n";
Expand All @@ -168,6 +197,19 @@ bool populate_devices(LuaScript& lScript)
GLOBAL::joyList.push_back(cJoy);
}//for


//Initilize the keyboards for input
cIndex = 0;
while(1)
{
bool noerr;
std::string kbdEventPath = lScript.get<std::string>("devices.kbd" + std::to_string(cIndex), noerr);
if(!noerr) break;
CKeyboard* nKBG = new CKeyboard(kbdEventPath);
GLOBAL::kbdList.push_back(nKBG);
cIndex++;
}//while

return true;
}

Expand Down Expand Up @@ -199,6 +241,8 @@ bool populate_virtual_devices(LuaScript& lScript)
GLOBAL::vJoyList.push_back(vJoy);
}//for

GLOBAL::vKeyboard = new CVirtualKeyboard();

return true;
}

Expand All @@ -220,14 +264,17 @@ void link_lua_functions(LuaScript& lScript)
int main(int argc, char** argv)
{
//TODO I need to search for information on which buttons and axes is required to correctly be found in applications, as sometimes i.e. axes are found in system, but not by applications.


std::cout << "WeJoy v0.2 by Johannes Bergmark\n";

if(argc<2)
{
std::cout << "Please type the path of your lua file.\n";
std::cout << "I.e. 'wejoy config.lua'\n";
return 0;
}


//Open the user lua file.
LuaScript lScript(argv[1]);
if(!lScript.isOpen()) return 0;
Expand All @@ -236,14 +283,21 @@ int main(int argc, char** argv)
if (!populate_virtual_devices(lScript)) exit(0);
link_lua_functions(lScript);


std::cout << "Press 'q' and then 'ENTER' to quit!\n";
std::thread threadUpdate(updateThread, std::ref(lScript));

std::thread threadUpdateJoysticks(updateThreadJoysticks, std::ref(lScript));
std::thread threadUpdateKeyboard(updateThreadKeyboard, std::ref(lScript));

while(getchar()!='q');
bPoll = false,
threadUpdate.join();
threadUpdateJoysticks.join();
threadUpdateKeyboard.join();
sleep(1);

for(unsigned int i=0; i<GLOBAL::kbdList.size(); i++) delete GLOBAL::kbdList[i];
delete GLOBAL::vKeyboard;

return 0;
}

2 changes: 1 addition & 1 deletion make.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/sh
#g++ -ludev suinput.o -o test main.cc -Wall
#g++ -Wall -std=c++11 -ludev -lpthread -lX11 -llua5.2 suinput.c joystick.cc LuaScript.cc CVirtualJoy.cc CVirtualKeyboard.cc -o wejoy main.cc
g++ -Wall -std=c++11 suinput.c joystick.cc LuaScript.cc CVirtualJoy.cc CVirtualKeyboard.cc -o wejoy main.cc -ludev -lpthread -lX11 -llua5.2
g++ -Wall -std=c++11 suinput.c joystick.cc CKeyboard.cc LuaScript.cc CVirtualJoy.cc CVirtualKeyboard.cc -o wejoy main.cc -ludev -lpthread -lX11 -llua5.2
#g++ test.cc joystick.cc -std=c++0x -Wall -o test

0 comments on commit 882c4ba

Please sign in to comment.