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
This commit is contained in:
Gregory Hainaut 2015-01-30 23:44:51 +01:00
parent aec43f0bee
commit 3096e94616
9 changed files with 177 additions and 2 deletions

View File

@ -30,6 +30,7 @@ set(lilypadSources
InputManager.cpp InputManager.cpp
Linux/Config.cpp Linux/Config.cpp
Linux/ConfigHelper.cpp Linux/ConfigHelper.cpp
Linux/KeyboardMouse.cpp
Linux/KeyboardQueue.cpp Linux/KeyboardQueue.cpp
Linux/LilyPad.cpp) Linux/LilyPad.cpp)

View File

@ -27,6 +27,10 @@
#include "HidDevice.h" #include "HidDevice.h"
#include "DualShock3.h" #include "DualShock3.h"
#ifdef __linux__
#include "Linux/KeyboardMouse.h"
#endif
void EnumDevices(int hideDXXinput) { void EnumDevices(int hideDXXinput) {
// Needed for enumeration of some device types. // Needed for enumeration of some device types.
dm->ReleaseInput(); dm->ReleaseInput();
@ -40,6 +44,8 @@ void EnumDevices(int hideDXXinput) {
EnumDualShock3s(); EnumDualShock3s();
EnumXInputDevices(); EnumXInputDevices();
EnumDirectInputDevices(hideDXXinput); EnumDirectInputDevices(hideDXXinput);
#else
EnumLnx();
#endif #endif
dm->CopyBindings(oldDm->numDevices, oldDm->devices); dm->CopyBindings(oldDm->numDevices, oldDm->devices);

View File

@ -130,6 +130,8 @@ enum DeviceAPI {
// to ignore individual buttons. Wrapper itself takes care // to ignore individual buttons. Wrapper itself takes care
// of ignoring bound keys. Otherwise, works normally. // of ignoring bound keys. Otherwise, works normally.
IGNORE_KEYBOARD = 7, IGNORE_KEYBOARD = 7,
// XXX
LNX_KEYBOARD = 16,
}; };
enum DeviceType { enum DeviceType {

View File

@ -24,3 +24,9 @@ int GetQueuedKeyEvent(keyEvent *event);
// Cleans up as well as clears queue. // Cleans up as well as clears queue.
void ClearKeyQueue(); void ClearKeyQueue();
#ifdef __linux__
void R_QueueKeyEvent(const keyEvent& event);
int R_GetQueuedKeyEvent(keyEvent *event);
void R_ClearKeyQueue();
#endif

View File

@ -158,8 +158,8 @@ int LoadSettings(int force, wchar_t *file) {
config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks"); config.closeHacks = (u8)cfg.ReadInt(L"General Settings", L"Close Hacks");
if (config.closeHacks&1) config.closeHacks &= ~2; if (config.closeHacks&1) config.closeHacks &= ~2;
config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", WM); config.keyboardApi = (DeviceAPI)cfg.ReadInt(L"General Settings", L"Keyboard Mode", LNX_KEYBOARD);
if (!config.keyboardApi) config.keyboardApi = WM; if (!config.keyboardApi) config.keyboardApi = LNX_KEYBOARD;
config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode"); config.mouseApi = (DeviceAPI) cfg.ReadInt(L"General Settings", L"Mouse Mode");
config.volume = cfg.ReadInt(L"General Settings", L"Volume", 100); config.volume = cfg.ReadInt(L"General Settings", L"Volume", 100);
@ -292,6 +292,7 @@ int LoadSettings(int force, wchar_t *file) {
config.multipleBinding = multipleBinding; config.multipleBinding = multipleBinding;
//TODO RefreshEnabledDevicesAndDisplay(1); //TODO RefreshEnabledDevicesAndDisplay(1);
RefreshEnabledDevices(1); // XXX For the moment only a subfonction
return 0; return 0;
} }
@ -314,6 +315,7 @@ void RefreshEnabledDevices(int updateDeviceList) {
for (int i=0; i<dm->numDevices; i++) { for (int i=0; i<dm->numDevices; i++) {
Device *dev = dm->devices[i]; Device *dev = dm->devices[i];
// XXX windows magic?
if (!dev->attached && dev->displayName[0] != '[') { if (!dev->attached && dev->displayName[0] != '[') {
wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12)); wchar_t *newName = (wchar_t*) malloc(sizeof(wchar_t) * (wcslen(dev->displayName) + 12));
wsprintfW(newName, L"[Detached] %s", dev->displayName); wsprintfW(newName, L"[Detached] %s", dev->displayName);
@ -328,6 +330,8 @@ void RefreshEnabledDevices(int updateDeviceList) {
((dev->api == DI && config.gameApis.directInput) || ((dev->api == DI && config.gameApis.directInput) ||
(dev->api == DS3 && config.gameApis.dualShock3) || (dev->api == DS3 && config.gameApis.dualShock3) ||
(dev->api == XINPUT && config.gameApis.xInput)))) { (dev->api == XINPUT && config.gameApis.xInput)))) {
dm->EnableDevice(i);
#if 0 // windows magic?
if (config.gameApis.dualShock3 && dev->api == DI && dev->displayName && if (config.gameApis.dualShock3 && dev->api == DI && dev->displayName &&
!wcsicmp(dev->displayName, L"DX PLAYSTATION(R)3 Controller")) { !wcsicmp(dev->displayName, L"DX PLAYSTATION(R)3 Controller")) {
dm->DisableDevice(i); dm->DisableDevice(i);
@ -335,6 +339,7 @@ void RefreshEnabledDevices(int updateDeviceList) {
else { else {
dm->EnableDevice(i); dm->EnableDevice(i);
} }
#endif
} }
else { else {
dm->DisableDevice(i); dm->DisableDevice(i);

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<MAX_KEYCODE; i++) {
AddPhysicalControl(PSHBTN, i, i);
}
}
int LinuxKeyboard::Activate(InitInfo* args) {
// Always active
active = 1;
AllocState();
#if 0
for (int vkey=5; vkey<256; vkey++) {
int value = (unsigned short)(((short)GetAsyncKeyState(vkey))>>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());
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "Global.h"
#include "InputManager.h"
#include "KeyboardQueue.h"
class LinuxKeyboard : public Device {
public:
LinuxKeyboard();
int Activate(InitInfo* args);
int Update();
};
void EnumLnx();

View File

@ -66,3 +66,46 @@ int GetQueuedKeyEvent(keyEvent *event) {
void ClearKeyQueue() { void ClearKeyQueue() {
lastQueuedEvent = nextQueuedEvent; 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<std::mutex> 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<std::mutex> 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

View File

@ -729,6 +729,7 @@ s32 CALLBACK PADinit(u32 flags) {
query.lastByte = 1; query.lastByte = 1;
query.numBytes = 0; query.numBytes = 0;
ClearKeyQueue(); ClearKeyQueue();
R_ClearKeyQueue();
// Just in case, when resuming emulation. // Just in case, when resuming emulation.
ReleaseModifierKeys(); ReleaseModifierKeys();
@ -811,6 +812,7 @@ void CALLBACK PADclose() {
DEBUG_TEXT_OUT("LilyPad closed\n\n"); DEBUG_TEXT_OUT("LilyPad closed\n\n");
updateQueued = 0; updateQueued = 0;
ClearKeyQueue(); ClearKeyQueue();
R_ClearKeyQueue();
} }
} }