From 3096e946163a9a1a388aef01d0c94a9d272af631 Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Fri, 30 Jan 2015 23:44:51 +0100 Subject: [PATCH] lilypad : plug a basic keyboard device Add a reverse fifo to transfer event from core to plugin Long story short, on linux there is only one event queue in core --- plugins/LilyPad/CMakeLists.txt | 1 + plugins/LilyPad/DeviceEnumerator.cpp | 6 ++ plugins/LilyPad/InputManager.h | 2 + plugins/LilyPad/KeyboardQueue.h | 6 ++ plugins/LilyPad/Linux/Config.cpp | 9 ++- plugins/LilyPad/Linux/KeyboardMouse.cpp | 81 +++++++++++++++++++++++++ plugins/LilyPad/Linux/KeyboardMouse.h | 29 +++++++++ plugins/LilyPad/Linux/KeyboardQueue.cpp | 43 +++++++++++++ plugins/LilyPad/Linux/LilyPad.cpp | 2 + 9 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 plugins/LilyPad/Linux/KeyboardMouse.cpp create mode 100644 plugins/LilyPad/Linux/KeyboardMouse.h diff --git a/plugins/LilyPad/CMakeLists.txt b/plugins/LilyPad/CMakeLists.txt index f7073171f1..7920f22ef4 100644 --- a/plugins/LilyPad/CMakeLists.txt +++ b/plugins/LilyPad/CMakeLists.txt @@ -30,6 +30,7 @@ set(lilypadSources InputManager.cpp Linux/Config.cpp Linux/ConfigHelper.cpp + Linux/KeyboardMouse.cpp Linux/KeyboardQueue.cpp Linux/LilyPad.cpp) diff --git a/plugins/LilyPad/DeviceEnumerator.cpp b/plugins/LilyPad/DeviceEnumerator.cpp index 01e6b9705f..c06088c3d8 100644 --- a/plugins/LilyPad/DeviceEnumerator.cpp +++ b/plugins/LilyPad/DeviceEnumerator.cpp @@ -27,6 +27,10 @@ #include "HidDevice.h" #include "DualShock3.h" +#ifdef __linux__ +#include "Linux/KeyboardMouse.h" +#endif + void EnumDevices(int hideDXXinput) { // Needed for enumeration of some device types. dm->ReleaseInput(); @@ -40,6 +44,8 @@ void EnumDevices(int hideDXXinput) { EnumDualShock3s(); EnumXInputDevices(); EnumDirectInputDevices(hideDXXinput); +#else + EnumLnx(); #endif dm->CopyBindings(oldDm->numDevices, oldDm->devices); diff --git a/plugins/LilyPad/InputManager.h b/plugins/LilyPad/InputManager.h index 87600703b8..62e3111da9 100644 --- a/plugins/LilyPad/InputManager.h +++ b/plugins/LilyPad/InputManager.h @@ -130,6 +130,8 @@ enum DeviceAPI { // to ignore individual buttons. Wrapper itself takes care // of ignoring bound keys. Otherwise, works normally. IGNORE_KEYBOARD = 7, + // XXX + LNX_KEYBOARD = 16, }; enum DeviceType { diff --git a/plugins/LilyPad/KeyboardQueue.h b/plugins/LilyPad/KeyboardQueue.h index 2512ca5375..f79ef32658 100644 --- a/plugins/LilyPad/KeyboardQueue.h +++ b/plugins/LilyPad/KeyboardQueue.h @@ -24,3 +24,9 @@ int GetQueuedKeyEvent(keyEvent *event); // Cleans up as well as clears queue. void ClearKeyQueue(); + +#ifdef __linux__ +void R_QueueKeyEvent(const keyEvent& event); +int R_GetQueuedKeyEvent(keyEvent *event); +void R_ClearKeyQueue(); +#endif diff --git a/plugins/LilyPad/Linux/Config.cpp b/plugins/LilyPad/Linux/Config.cpp index 725efa2e76..0b40914353 100644 --- a/plugins/LilyPad/Linux/Config.cpp +++ b/plugins/LilyPad/Linux/Config.cpp @@ -158,8 +158,8 @@ int LoadSettings(int force, wchar_t *file) { config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks"); if (config.closeHacks&1) config.closeHacks &= ~2; - config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", WM); - if (!config.keyboardApi) config.keyboardApi = WM; + config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD); + if (!config.keyboardApi) config.keyboardApi = LNX_KEYBOARD; config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode"); config.volume = cfg.ReadInt(L"General Settings", L"Volume", 100); @@ -292,6 +292,7 @@ int LoadSettings(int force, wchar_t *file) { config.multipleBinding = multipleBinding; //TODO RefreshEnabledDevicesAndDisplay(1); + RefreshEnabledDevices(1); // XXX For the moment only a subfonction return 0; } @@ -314,6 +315,7 @@ void RefreshEnabledDevices(int updateDeviceList) { for (int i=0; inumDevices; i++) { Device *dev = dm->devices[i]; + // XXX windows magic? if (!dev->attached && dev->displayName[0] != '[') { wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12)); wsprintfW(newName, L"[Detached] %s", dev->displayName); @@ -328,6 +330,8 @@ void RefreshEnabledDevices(int updateDeviceList) { ((dev->api == DI && config.gameApis.directInput) || (dev->api == DS3 && config.gameApis.dualShock3) || (dev->api == XINPUT && config.gameApis.xInput)))) { + dm->EnableDevice(i); +#if 0 // windows magic? if (config.gameApis.dualShock3 && dev->api == DI && dev->displayName && !wcsicmp(dev->displayName, L"DX PLAYSTATION(R)3 Controller")) { dm->DisableDevice(i); @@ -335,6 +339,7 @@ void RefreshEnabledDevices(int updateDeviceList) { else { dm->EnableDevice(i); } +#endif } else { dm->DisableDevice(i); diff --git a/plugins/LilyPad/Linux/KeyboardMouse.cpp b/plugins/LilyPad/Linux/KeyboardMouse.cpp new file mode 100644 index 0000000000..c520227f2d --- /dev/null +++ b/plugins/LilyPad/Linux/KeyboardMouse.cpp @@ -0,0 +1,81 @@ +/* LilyPad - Pad plugin for PS2 Emulator + * Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver + * + * PCSX2 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Found- ation, either version 3 of the License, or (at your option) + * any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with PCSX2. If not, see . + */ + +#include "Linux/KeyboardMouse.h" + +// actually it is even more but it is enough to distinguish different key +#define MAX_KEYCODE (0xFF) + +LinuxKeyboard::LinuxKeyboard() : + Device(LNX_KEYBOARD, KEYBOARD, L"displayName", L"instanceID", L"deviceID") +{ + fprintf(stderr, "Create a new device YES\n"); + for (int i=0; i>15); + value += value&1; + if (vkey == VK_CONTROL || vkey == VK_MENU || vkey == VK_SHIFT) { + value = 0; + } + physicalControlState[vkey] = 0; + } +#endif + // Every button released + memset(physicalControlState, 0, sizeof(int)*MAX_KEYCODE); + + return 1; +} + +int LinuxKeyboard::Update() { + keyEvent event; + int status = 0; + while (R_GetQueuedKeyEvent(&event)) { + switch (event.evt) { + case KeyPress: + fprintf(stderr, "key pressed %x\n", event.key); + physicalControlState[MAX_KEYCODE & event.key] = FULLY_DOWN; + status = 1; + break; + case KeyRelease: + fprintf(stderr, "key released %x\n", event.key); + physicalControlState[MAX_KEYCODE & event.key] = 0; + status = 1; + break; + default: + fprintf(stderr, "Unsupported event %x\n", event.evt); + //assert(0); + break; + } + } + + return status; // XXX ???? +} + +void EnumLnx() { + dm->AddDevice(new LinuxKeyboard()); +} diff --git a/plugins/LilyPad/Linux/KeyboardMouse.h b/plugins/LilyPad/Linux/KeyboardMouse.h new file mode 100644 index 0000000000..b336b2a842 --- /dev/null +++ b/plugins/LilyPad/Linux/KeyboardMouse.h @@ -0,0 +1,29 @@ +/* LilyPad - Pad plugin for PS2 Emulator + * Copyright (C) 2002-2015 PCSX2 Dev Team/ChickenLiver + * + * PCSX2 is free software: you can redistribute it and/or modify it under the + * terms of the GNU Lesser General Public License as published by the Free + * Software Found- ation, either version 3 of the License, or (at your option) + * any later version. + * + * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with PCSX2. If not, see . + */ + +#include "Global.h" +#include "InputManager.h" +#include "KeyboardQueue.h" + +class LinuxKeyboard : public Device { + public: + LinuxKeyboard(); + int Activate(InitInfo* args); + int Update(); +}; + +void EnumLnx(); diff --git a/plugins/LilyPad/Linux/KeyboardQueue.cpp b/plugins/LilyPad/Linux/KeyboardQueue.cpp index 3718834f3c..55fffd8a2b 100644 --- a/plugins/LilyPad/Linux/KeyboardQueue.cpp +++ b/plugins/LilyPad/Linux/KeyboardQueue.cpp @@ -66,3 +66,46 @@ int GetQueuedKeyEvent(keyEvent *event) { void ClearKeyQueue() { lastQueuedEvent = nextQueuedEvent; } + + +#ifdef __linux__ +// Above code is for events that go from the plugin to core +// Here we need the contrary, event that come from core to the plugin +// Yes it is a crazy ping-pong hell ! I mostly copy past with +// a R_ (which stand for reverse) + +#define R_EVENT_QUEUE_LEN 256 +static std::mutex core_event; + +static u8 R_lastQueuedEvent = 0; +static u8 R_nextQueuedEvent = 0; +static keyEvent R_queuedEvents[R_EVENT_QUEUE_LEN]; + +void R_QueueKeyEvent(const keyEvent &evt) { + std::lock_guard lock(cSection); + + R_queuedEvents[R_lastQueuedEvent] = evt; + R_lastQueuedEvent = (R_lastQueuedEvent + 1) % R_EVENT_QUEUE_LEN; + // In case someone has a severe Parkingson's disease + assert(R_nextQueuedEvent != R_lastQueuedEvent); +} + +int R_GetQueuedKeyEvent(keyEvent *event) { + if (R_lastQueuedEvent == R_nextQueuedEvent) return 0; + + std::lock_guard lock(core_event); + *event = R_queuedEvents[R_nextQueuedEvent]; + R_nextQueuedEvent = (R_nextQueuedEvent + 1) % R_EVENT_QUEUE_LEN; + return 1; +} + +void R_ClearKeyQueue() { + R_lastQueuedEvent = R_nextQueuedEvent; +} + +EXPORT_C_(void) PADWriteEvent(keyEvent &evt) +{ + //fprintf(stderr, "Received evt:%x key:%x\n", evt.evt, evt.key); + R_QueueKeyEvent(evt); +} +#endif diff --git a/plugins/LilyPad/Linux/LilyPad.cpp b/plugins/LilyPad/Linux/LilyPad.cpp index fb7a7fca73..c802d7e57f 100644 --- a/plugins/LilyPad/Linux/LilyPad.cpp +++ b/plugins/LilyPad/Linux/LilyPad.cpp @@ -729,6 +729,7 @@ s32 CALLBACK PADinit(u32 flags) { query.lastByte = 1; query.numBytes = 0; ClearKeyQueue(); + R_ClearKeyQueue(); // Just in case, when resuming emulation. ReleaseModifierKeys(); @@ -811,6 +812,7 @@ void CALLBACK PADclose() { DEBUG_TEXT_OUT("LilyPad closed\n\n"); updateQueued = 0; ClearKeyQueue(); + R_ClearKeyQueue(); } }