From 882c4babcb004606fb8720be6a510a221fbeb28f Mon Sep 17 00:00:00 2001 From: Johannes Bergmark Date: Tue, 13 Aug 2019 13:49:26 +0200 Subject: [PATCH] Added keyboard input detection Also, edited the LuaScript source to remove some irritating false errors when running WeJoy, and some other clean up which I do not remember. --- CKeyboard.cc | 64 ++++++++++++++++++++++++++++++++++ CKeyboard.h | 29 ++++++++++++++++ CVirtualJoy.cc | 2 -- CVirtualKeyboard.cc | 2 -- example.lua | 15 ++++++++ global.h | 4 ++- main.cc | 84 +++++++++++++++++++++++++++++++++++++-------- make.sh | 2 +- 8 files changed, 181 insertions(+), 21 deletions(-) create mode 100644 CKeyboard.cc create mode 100644 CKeyboard.h diff --git a/CKeyboard.cc b/CKeyboard.cc new file mode 100644 index 0000000..067fc77 --- /dev/null +++ b/CKeyboard.cc @@ -0,0 +1,64 @@ +#include "CKeyboard.h" +//#include +//#include +#include +#include //usleep +#include +#include +#include + + +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; +} diff --git a/CKeyboard.h b/CKeyboard.h new file mode 100644 index 0000000..fbc65fc --- /dev/null +++ b/CKeyboard.h @@ -0,0 +1,29 @@ +#ifndef CKEYBOARD_HEADER +#define CKEYBOARD_HEADER + +#include + + +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 diff --git a/CVirtualJoy.cc b/CVirtualJoy.cc index d479384..fd02e4c 100644 --- a/CVirtualJoy.cc +++ b/CVirtualJoy.cc @@ -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) @@ -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)); diff --git a/CVirtualKeyboard.cc b/CVirtualKeyboard.cc index 0cca0d0..7c946f4 100644 --- a/CVirtualKeyboard.cc +++ b/CVirtualKeyboard.cc @@ -6,7 +6,6 @@ CVirtualKeyboard::CVirtualKeyboard() { - std::cout << "Opening virtual keyboard device.\n"; //Get a device descriptor fd = suinput_open(); if(fd<0) @@ -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)); diff --git a/example.lua b/example.lua index 508f271..7754805 100644 --- a/example.lua +++ b/example.lua @@ -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. @@ -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) diff --git a/global.h b/global.h index fa1c36a..54888cc 100644 --- a/global.h +++ b/global.h @@ -2,6 +2,7 @@ #define GLOBAL_H #include +#include "CKeyboard.h" #include "joystick.h" #include "CVirtualJoy.h" #include "CVirtualKeyboard.h" @@ -10,7 +11,8 @@ namespace GLOBAL { std::vector joyList; std::vector vJoyList; - CVirtualKeyboard vKeyboard; + std::vector kbdList; + CVirtualKeyboard* vKeyboard; } #endif diff --git a/main.cc b/main.cc index fbc2be1..546571e 100644 --- a/main.cc +++ b/main.cc @@ -1,27 +1,56 @@ #include //sleep #include //thread +#include #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; ireadJoy(&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; ireadJoy(&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; ireadEvent(&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 @@ -29,7 +58,7 @@ 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; } @@ -157,7 +186,7 @@ bool populate_devices(LuaScript& lScript) //Populate the list of found joysticks for(unsigned int i=0; iisFound()) { std::cout << "WARNING: Joystick " << std::hex << dList[i][0] << ":" << std::hex << dList[i][1] << " is not found.\n"; @@ -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("devices.kbd" + std::to_string(cIndex), noerr); + if(!noerr) break; + CKeyboard* nKBG = new CKeyboard(kbdEventPath); + GLOBAL::kbdList.push_back(nKBG); + cIndex++; + }//while + return true; } @@ -199,6 +241,8 @@ bool populate_virtual_devices(LuaScript& lScript) GLOBAL::vJoyList.push_back(vJoy); }//for + GLOBAL::vKeyboard = new CVirtualKeyboard(); + return true; } @@ -220,7 +264,9 @@ 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"; @@ -228,6 +274,7 @@ int main(int argc, char** argv) return 0; } + //Open the user lua file. LuaScript lScript(argv[1]); if(!lScript.isOpen()) return 0; @@ -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