RaspberryPi Keyboard input with evdev
Based on pull request from user "DarkElvenAngel", better integrated with the current event system and enhanced with buffer to help with fast typing at low framerates.
This commit is contained in:
parent
7524fdc3e1
commit
b1e914bbf3
85
src/core.c
85
src/core.c
@ -361,6 +361,15 @@ typedef struct {
|
||||
|
||||
static InputEventWorker eventWorkers[10]; // List of worker threads for every monitored "/dev/input/event<N>"
|
||||
|
||||
typedef struct{
|
||||
int Contents[8];
|
||||
char Head;
|
||||
char Tail;
|
||||
} KeyEventFifo;
|
||||
|
||||
static KeyEventFifo lastKeyPressedEvdev; // Buffer for holding keydown events as they arrive (Needed due to multitreading of event workers)
|
||||
static char currentKeyStateEvdev[512] = { 0 }; // Registers current frame key state from event based driver (Needs to be seperate because the legacy console based method clears keys on every frame)
|
||||
|
||||
#endif
|
||||
#if defined(PLATFORM_WEB)
|
||||
static bool toggleCursorLock = false; // Ask for cursor pointer lock on next click
|
||||
@ -470,7 +479,7 @@ static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadE
|
||||
static void InitKeyboard(void); // Init raw keyboard system (standard input reading)
|
||||
static void ProcessKeyboard(void); // Process keyboard events
|
||||
static void RestoreKeyboard(void); // Restore keyboard system
|
||||
static void InitMouse(void); // Mouse initialization (including mouse thread)
|
||||
static void InitEvdevInput(void); // Mouse initialization (including mouse thread)
|
||||
static void EventThreadSpawn(char *device); // Identifies a input device and spawns a thread to handle it if needed
|
||||
static void *EventThread(void *arg); // Input device events reading thread
|
||||
static void InitGamepad(void); // Init raw gamepad input
|
||||
@ -590,7 +599,7 @@ void InitWindow(int width, int height, const char *title)
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
// Init raw input system
|
||||
InitMouse(); // Mouse init
|
||||
InitEvdevInput(); // Mouse init
|
||||
InitKeyboard(); // Keyboard init
|
||||
InitGamepad(); // Gamepad init
|
||||
#endif
|
||||
@ -3054,8 +3063,16 @@ static void PollInputEvents(void)
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
|
||||
// Register previous keys states
|
||||
for (int i = 0; i < 512; i++) previousKeyState[i] = currentKeyState[i];
|
||||
for (int i = 0; i < 512; i++)previousKeyState[i] = currentKeyState[i];
|
||||
|
||||
// Grab a keypress from the evdev fifo if avalable
|
||||
if(lastKeyPressedEvdev.Head != lastKeyPressedEvdev.Tail)
|
||||
{
|
||||
lastKeyPressed = lastKeyPressedEvdev.Contents[lastKeyPressedEvdev.Tail]; // Read the key from the buffer
|
||||
lastKeyPressedEvdev.Tail = (lastKeyPressedEvdev.Tail + 1) & 0x07; // Increment the tail pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
||||
}
|
||||
|
||||
// Register previous mouse states
|
||||
previousMouseWheelY = currentMouseWheelY;
|
||||
@ -3211,10 +3228,10 @@ static void PollInputEvents(void)
|
||||
#endif
|
||||
|
||||
#if defined(PLATFORM_RPI)
|
||||
// NOTE: Mouse input events polling is done asynchonously in another pthread - MouseThread()
|
||||
// NOTE: Mouse input events polling is done asynchonously in another pthread - EventThread()
|
||||
|
||||
// NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin,
|
||||
// we use method 2 (stdin) but maybe in a future we should change to method 1...
|
||||
// we now use both methods inside here. 2nd method is still used for legacy purposes (Allows for input trough SSH console)
|
||||
ProcessKeyboard();
|
||||
|
||||
// NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread()
|
||||
@ -3921,6 +3938,9 @@ static void ProcessKeyboard(void)
|
||||
// Reset pressed keys array (it will be filled below)
|
||||
for (int i = 0; i < 512; i++) currentKeyState[i] = 0;
|
||||
|
||||
// Check keys from event input workers (This is the new keyboard reading method)
|
||||
for (int i = 0; i < 512; i++)currentKeyState[i] = currentKeyStateEvdev[i];
|
||||
|
||||
// Fill all read bytes (looking for keys)
|
||||
for (int i = 0; i < bufferByteCount; i++)
|
||||
{
|
||||
@ -4021,8 +4041,8 @@ static void RestoreKeyboard(void)
|
||||
ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode);
|
||||
}
|
||||
|
||||
// Mouse initialization (including mouse thread)
|
||||
static void InitMouse(void)
|
||||
// Initialise user input from evdev(/dev/input/event<N>) this means mouse, keyboard or gamepad devices
|
||||
static void InitEvdevInput(void)
|
||||
{
|
||||
char path[MAX_FILEPATH_LENGTH];
|
||||
DIR *directory;
|
||||
@ -4034,6 +4054,11 @@ static void InitMouse(void)
|
||||
touchPosition[i].x = -1;
|
||||
touchPosition[i].y = -1;
|
||||
}
|
||||
// Reset keypress buffer
|
||||
lastKeyPressedEvdev.Head = 0;
|
||||
lastKeyPressedEvdev.Tail = 0;
|
||||
// Reset keyboard key state
|
||||
for (int i = 0; i < 512; i++) currentKeyStateEvdev[i] = 0;
|
||||
|
||||
// Open the linux directory of "/dev/input"
|
||||
directory = opendir(DEFAULT_EVDEV_PATH);
|
||||
@ -4202,7 +4227,7 @@ static void EventThreadSpawn(char *device)
|
||||
|
||||
// Decide what to do with the device
|
||||
//-------------------------------------------------------------------------------------------------------
|
||||
if (worker->isTouch || worker->isMouse)
|
||||
if (worker->isTouch || worker->isMouse || worker->isKeyboard)
|
||||
{
|
||||
// Looks like a interesting device
|
||||
TraceLog(LOG_INFO, "Opening input device [%s] (%s%s%s%s%s)", device,
|
||||
@ -4252,14 +4277,35 @@ static void EventThreadSpawn(char *device)
|
||||
// Input device events reading thread
|
||||
static void *EventThread(void *arg)
|
||||
{
|
||||
// Scancode to keycode mapping for US keyboards
|
||||
// TODO: Proabobly replace this with a keymap from the X11 to get the correct regional map for the keyboard (Currently non US keyboards will have the wrong mapping for some keys)
|
||||
static const int keymap_US[] =
|
||||
{0,256,49,50,51,52,53,54,55,56,57,48,45,61,259,258,81,87,69,82,84,
|
||||
89,85,73,79,80,91,93,257,341,65,83,68,70,71,72,74,75,76,59,39,96,
|
||||
340,92,90,88,67,86,66,78,77,44,46,47,344,332,342,32,280,290,291,
|
||||
292,293,294,295,296,297,298,299,282,281,327,328,329,333,324,325,
|
||||
326,334,321,322,323,320,330,0,85,86,300,301,89,90,91,92,93,94,95,
|
||||
335,345,331,283,346,101,268,265,266,263,262,269,264,267,260,261,
|
||||
112,113,114,115,116,117,118,119,120,121,122,123,124,125,347,127,
|
||||
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
|
||||
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
|
||||
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
|
||||
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
|
||||
192,193,194,0,0,0,0,0,200,201,202,203,204,205,206,207,208,209,210,
|
||||
211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,
|
||||
227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,
|
||||
243,244,245,246,247,248,0,0,0,0,0,0,0,};
|
||||
|
||||
struct input_event event;
|
||||
InputEventWorker *worker = (InputEventWorker *)arg;
|
||||
|
||||
int touchAction = -1;
|
||||
bool gestureUpdate = false;
|
||||
int keycode;
|
||||
|
||||
while (!windowShouldClose)
|
||||
{
|
||||
// Try to read data from the device and only continue if successful
|
||||
if (read(worker->fd, &event, sizeof(event)) == (int)sizeof(event))
|
||||
{
|
||||
// Relative movement parsing
|
||||
@ -4341,6 +4387,8 @@ static void *EventThread(void *arg)
|
||||
// Button parsing
|
||||
if (event.type == EV_KEY)
|
||||
{
|
||||
|
||||
// Mouse button parsing
|
||||
if ((event.code == BTN_TOUCH) || (event.code == BTN_LEFT))
|
||||
{
|
||||
currentMouseStateEvdev[MOUSE_LEFT_BUTTON] = event.value;
|
||||
@ -4353,6 +4401,27 @@ static void *EventThread(void *arg)
|
||||
if (event.code == BTN_RIGHT) currentMouseStateEvdev[MOUSE_RIGHT_BUTTON] = event.value;
|
||||
|
||||
if (event.code == BTN_MIDDLE) currentMouseStateEvdev[MOUSE_MIDDLE_BUTTON] = event.value;
|
||||
|
||||
// Keyboard button parsing
|
||||
if((event.code >= 1) && (event.code <= 255)) //Keyboard keys appear for codes 1 to 255
|
||||
{
|
||||
keycode = keymap_US[event.code & 0xFF]; // The code we get is a scancode so we look up the apropriate keycode
|
||||
// Make sure we got a valid keycode
|
||||
if((keycode > 0) && (keycode < sizeof(currentKeyState)))
|
||||
{
|
||||
// Store the key information for raylib to later use
|
||||
currentKeyStateEvdev[keycode] = event.value;
|
||||
if(event.value > 0)
|
||||
{
|
||||
// Add the key int the fifo
|
||||
lastKeyPressedEvdev.Contents[lastKeyPressedEvdev.Head] = keycode; // Put the data at the front of the fifo snake
|
||||
lastKeyPressedEvdev.Head = (lastKeyPressedEvdev.Head + 1) & 0x07; // Increment the head pointer forwards and binary wraparound after 7 (fifo is 8 elements long)
|
||||
// TODO: This fifo is not fully threadsafe with multiple writers, so multiple keyboards hitting a key at the exact same time could miss a key (double write to head before it was incremented)
|
||||
}
|
||||
TraceLog(LOG_DEBUG, "KEY%s ScanCode: %4i KeyCode: %4i",event.value == 0 ? "UP":"DOWN", event.code, keycode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Screen confinement
|
||||
|
Loading…
Reference in New Issue
Block a user