diff --git a/src/rcore.h b/src/rcore.h index 7f12a29ea..1127585a0 100644 --- a/src/rcore.h +++ b/src/rcore.h @@ -179,7 +179,7 @@ typedef struct CoreData { } Touch; struct { int lastButtonPressed; // Register last gamepad button pressed - int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axis + int axisCount[MAX_GAMEPADS]; // Register number of available gamepad axis bool ready[MAX_GAMEPADS]; // Flag to know if gamepad is ready char name[MAX_GAMEPADS][64]; // Gamepad name holder char currentButtonState[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Current gamepad buttons state diff --git a/src/rcore_android.c b/src/rcore_android.c index b7680adbc..97a8522d2 100644 --- a/src/rcore_android.c +++ b/src/rcore_android.c @@ -566,7 +566,7 @@ void PollInputEvents(void) // Reset last gamepad button/axis registered state CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN - CORE.Input.Gamepad.axisCount = 0; + //CORE.Input.Gamepad.axisCount = 0; // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; diff --git a/src/rcore_drm.c b/src/rcore_drm.c index 82d95b22f..994d86bfc 100644 --- a/src/rcore_drm.c +++ b/src/rcore_drm.c @@ -72,24 +72,13 @@ //---------------------------------------------------------------------------------- #define USE_LAST_TOUCH_DEVICE // When multiple touchscreens are connected, only use the one with the highest event number -#define DEFAULT_EVDEV_PATH "/dev/input/by-id" // Path to the linux input events - -#define MI_BITS_PER_LONG (8 * sizeof(long)) -#define MI_NBITS(x) ((((x)-1) / MI_BITS_PER_LONG) + 1) -#define MI_OFF(x) ((x) % MI_BITS_PER_LONG) -#define MI_BIT(x) (1UL << MI_OFF(x)) -#define MI_LONG(x) ((x) / MI_BITS_PER_LONG) -#define MI_IS_BIT_SET(array, bit) ((array[MI_LONG(bit)] >> MI_OFF(bit)) & 1) +#define DEFAULT_GAMEPAD_DEV "/dev/input/js" // Gamepad input (base dev for all gamepads: js0, js1, ...) +#define DEFAULT_EVDEV_PATH "/dev/input/" // Path to the linux input events //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef struct { - int min; - int max; -} GamepadAxisRange; - typedef struct { pthread_t threadId; // Event reading thread id @@ -136,13 +125,9 @@ typedef struct { char currentButtonStateEvdev[MAX_MOUSE_BUTTONS]; // Holds the new mouse state for the next polling event to grab // Gamepad data - pthread_t gamepadThreadId; // Gamepad reading thread id - int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor - struct input_absinfo gamepadAxisFeatures[MAX_GAMEPADS][ABS_MAX]; // Store the features of each axis for each gamepad. - int gamepadActiveAxes[MAX_GAMEPADS][MAX_GAMEPAD_AXIS]; // Map axis ID to actual axis, e.g. the first axis found will be axis 0 as far as raylib is concerned but might actually be ABS_HAT0X (16) for some gamepads. - int gamepadButtonCount[MAX_GAMEPADS]; // Store the number of active buttons found, up to MAX_GAMEPAD_BUTTONS - int gamepadActiveButtons[MAX_GAMEPADS][MAX_GAMEPAD_BUTTONS]; // Map button ID to actual key. e.g. the first key on a joystick might be KEY_A or KEY_X. - + pthread_t gamepadThreadId; // Gamepad reading thread id + int gamepadStreamFd[MAX_GAMEPADS]; // Gamepad device file descriptor + } PlatformData; //---------------------------------------------------------------------------------- @@ -164,17 +149,13 @@ static void RestoreKeyboard(void); // Restore keyboard system static void ProcessKeyboard(void); // Process keyboard events #endif -static void InitDrmInput(void); // Initialize inputs for DRM platform -static void InitDrmJoystick(int index, const char *path); // Initialize a joystick for DRM platform -static void PollDrmJoystickEvents(); +static void InitEvdevInput(void); // Initialize evdev inputs +static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate +static void PollKeyboardEvents(void); // Process evdev keyboard events +static void *EventThread(void *arg); // Input device events reading thread -static void InitEvdevInput(void); // Initialize evdev inputs -static void ConfigureEvdevDevice(char *device); // Identifies a input device and configures it for use if appropriate -static void PollKeyboardEvents(void); // Process evdev keyboard events -static void *EventThread(void *arg); // Input device events reading thread - -//static void InitGamepad(void); // Initialize raw gamepad input -//static void *GamepadThread(void *arg); // Mouse reading thread +static void InitGamepad(void); // Initialize raw gamepad input +static void *GamepadThread(void *arg); // Mouse reading thread static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode); // Search matching DRM mode in connector's mode list static int FindExactConnectorMode(const drmModeConnector *connector, uint width, uint height, uint fps, bool allowInterlaced); // Search exactly matching DRM connector mode in connector's list @@ -676,7 +657,8 @@ void PollInputEvents(void) // Reset last gamepad button/axis registered state CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN - + //CORE.Input.Gamepad.axisCount = 0; + // Register previous keys states for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) { @@ -684,7 +666,6 @@ void PollInputEvents(void) CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; } - PollDrmJoystickEvents(); PollKeyboardEvents(); // Register previous mouse states @@ -1074,8 +1055,7 @@ static int InitPlatform(void) // Initialize raw input system InitEvdevInput(); // Evdev inputs initialization - InitDrmInput(); - //InitGamepad(); // Gamepad init + InitGamepad(); // Gamepad init InitKeyboard(); // Keyboard init (stdin) return 0; @@ -1345,165 +1325,6 @@ static void ProcessKeyboard(void) } #endif // SUPPORT_SSH_KEYBOARD_RPI -// Initialize user input from /dev/input/by-id -// This includes keyobard, mouse, gamepads, and touch screens. -static void InitDrmInput(void) -{ - TraceLog(LOG_INFO, "RUNNING InitDrmInput"); - - char path[MAX_FILEPATH_LENGTH] = { 0 }; - DIR *directory = NULL; - struct dirent *entity = NULL; - - // Initialise keyboard file descriptor - platform.keyboardFd = -1; - - // Reset variables - for (int i = 0; i < MAX_TOUCH_POINTS; ++i) - { - CORE.Input.Touch.position[i].x = -1; - CORE.Input.Touch.position[i].y = -1; - } - - // Reset keyboard key state - for (int i = 0; i < MAX_KEYBOARD_KEYS; i++) - { - CORE.Input.Keyboard.currentKeyState[i] = 0; - CORE.Input.Keyboard.keyRepeatInFrame[i] = 0; - } - - // Open the linux directory of "/dev/input/by-id" - directory = opendir(DEFAULT_EVDEV_PATH); - - if (directory) - { - while ((entity = readdir(directory)) != NULL) - { - sprintf(path, "%s/%s", DEFAULT_EVDEV_PATH, entity->d_name); - - // Devices are in the format: - // /dev/input/by-id/usb-Name_of_Device-[event-joystick|event-kbd|event-mouse] - int len = strlen("event-joystick"); - if (strncmp("event-joystick", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-joystick" - { - TraceLog(LOG_INFO, TextFormat("Device %s is an event joystick", entity->d_name)); - for (int i = 0; i < MAX_GAMEPADS; i++) - { - if (CORE.Input.Gamepad.ready[i]) - continue; - - InitDrmJoystick(i, path); - break; - } - } - - len = strlen("event-kbd"); - if (strncmp("event-kbd", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-kbd" - { - TraceLog(LOG_INFO, TextFormat("Device %s is an event keyboard", entity->d_name)); - } - - len = strlen("event-mouse"); - if (strncmp("event-mouse", entity->d_name + (strlen(entity->d_name)-len), len) == 0) // If the device id ends with "event-mouse" - { - TraceLog(LOG_INFO, TextFormat("Device %s is an event mouse", entity->d_name)); - } - } - - closedir(directory); - } -} - -static void InitDrmJoystick(int index, const char *path) -{ - TraceLog(LOG_INFO, TextFormat("InitDrmJoystick - %s", path)); - - platform.gamepadStreamFd[index] = open(path, O_RDONLY | O_NONBLOCK); - - // Get the name of the device. - ioctl(platform.gamepadStreamFd[index], EVIOCGNAME(64), &CORE.Input.Gamepad.name[index]); - - // Get the bits describing the buttons of the device. - unsigned long key_bits[KEY_MAX / 8 + 1] = {0}; - ioctl(platform.gamepadStreamFd[index], EVIOCGBIT(EV_KEY, sizeof(key_bits)), &key_bits); - - // Count the buttons present and map a game button id (0-32) to the key code of the physical button. - for (int key = 0; key < KEY_MAX; key++) - { - if (MI_IS_BIT_SET(key_bits, key) && platform.gamepadButtonCount[index] < MAX_GAMEPAD_BUTTONS) - { - platform.gamepadActiveButtons[index][platform.gamepadButtonCount[index]++] = key; - } - } - - // Get the bits describing the absolute axes of the device. - unsigned long abs_bits[ABS_MAX / 8 + 1] = {0}; - ioctl(platform.gamepadStreamFd[index], EVIOCGBIT(EV_ABS, sizeof(abs_bits)), &abs_bits); - - // Count the axes present on the device and read their features. - CORE.Input.Gamepad.axisCount[index] = 0; - for (int axis = 0; axis < ABS_MAX; axis++) - { - // axis may be any number between 0x00 and 0x3f, and it is common for the first axis to be 0x10 (ABS_HAT0X). This maps the active axes to a range of IDs between 0 and MAX_GAMEPAD_AXIS - if (MI_IS_BIT_SET(abs_bits, axis) && CORE.Input.Gamepad.axisCount[index] < MAX_GAMEPAD_AXIS) - { - platform.gamepadActiveAxes[index][CORE.Input.Gamepad.axisCount[index]++] = axis; - TraceLog(LOG_INFO, TextFormat("Gamepad %d has axis %d", index, axis)); - ioctl(platform.gamepadStreamFd[index], EVIOCGABS(axis), &platform.gamepadAxisFeatures[index][axis]); - } - } - - TraceLog(LOG_INFO, TextFormat("Gamepad [%d] %s has %d axes", index, CORE.Input.Gamepad.name[index], CORE.Input.Gamepad.axisCount[index])); - - CORE.Input.Gamepad.ready[index] = true; -} - -static void PollDrmJoystickEvents() -{ - struct input_event ev; - - for (int i = 0; i < MAX_GAMEPADS; i++) - { - if (!CORE.Input.Gamepad.ready[i]) - continue; - - while (read(platform.gamepadStreamFd[i], &ev, sizeof(ev)) > 0) - { - switch(ev.type) - { - case EV_KEY: - if (ev.code < KEY_MAX) - { - CORE.Input.Gamepad.currentButtonState[i][ev.code] = ev.value; - for (int lookupButton = 0; lookupButton < MAX_GAMEPAD_BUTTONS; lookupButton++) - { - if (platform.gamepadActiveButtons[i][lookupButton] == ev.code) - { - CORE.Input.Gamepad.currentButtonState[i][lookupButton] = ev.value; - break; - } - } - } - break; - case EV_ABS: - if (ev.code < MAX_GAMEPAD_AXIS) - { - struct input_absinfo f = platform.gamepadAxisFeatures[i][ev.code]; - for (int lookupAxis = 0; lookupAxis < MAX_GAMEPAD_AXIS; lookupAxis++) - { - if (platform.gamepadActiveAxes[i][lookupAxis] == ev.code) - { - CORE.Input.Gamepad.axisState[i][lookupAxis] = ((float)ev.value - ((f.maximum - f.minimum) / 2.0f)) / (float)(f.maximum - f.minimum); - break; - } - } - } - break; - } - } - } -} - // Initialise user input from evdev(/dev/input/event) // this means mouse, keyboard or gamepad devices static void InitEvdevInput(void) @@ -2001,39 +1822,38 @@ static void *EventThread(void *arg) } // Initialize gamepad system -// static void InitGamepad(void) -// { -// char gamepadDev[128] = { 0 }; -// -// for (int i = 0; i < MAX_GAMEPADS; i++) -// { -// sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i); -// -// if ((platform.gamepadStreamFd[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0) -// { -// // NOTE: Only show message for first gamepad -// if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available"); -// } -// else -// { -// CORE.Input.Gamepad.ready[i] = true; -// -// // NOTE: Only create one thread -// if (i == 0) -// { -// int error = pthread_create(&platform.gamepadThreadId, NULL, &GamepadThread, NULL); -// -// if (error != 0) TRACELOG(LOG_WARNING, "RPI: Failed to create gamepad input event thread"); -// else TRACELOG(LOG_INFO, "RPI: Gamepad device initialized successfully"); -// } -// -// ioctl(platform.gamepadStreamFd[i], JSIOCGNAME(64), &CORE.Input.Gamepad.name[i]); -// ioctl(platform.gamepadStreamFd[i], JSIOCGAXES, &CORE.Input.Gamepad.axisCount); -// } -// } -// } +static void InitGamepad(void) +{ + char gamepadDev[128] = { 0 }; + + for (int i = 0; i < MAX_GAMEPADS; i++) + { + sprintf(gamepadDev, "%s%i", DEFAULT_GAMEPAD_DEV, i); + + if ((platform.gamepadStreamFd[i] = open(gamepadDev, O_RDONLY | O_NONBLOCK)) < 0) + { + // NOTE: Only show message for first gamepad + if (i == 0) TRACELOG(LOG_WARNING, "RPI: Failed to open Gamepad device, no gamepad available"); + } + else + { + CORE.Input.Gamepad.ready[i] = true; + + // NOTE: Only create one thread + if (i == 0) + { + int error = pthread_create(&platform.gamepadThreadId, NULL, &GamepadThread, NULL); + + if (error != 0) TRACELOG(LOG_WARNING, "RPI: Failed to create gamepad input event thread"); + else TRACELOG(LOG_INFO, "RPI: Gamepad device initialized successfully"); + } + + ioctl(platform.gamepadStreamFd[i], JSIOCGNAME(64), &CORE.Input.Gamepad.name[i]); + ioctl(platform.gamepadStreamFd[i], JSIOCGAXES, &CORE.Input.Gamepad.axisCount[i]); + } + } +} -/* // Process Gamepad (/dev/input/js0) static void *GamepadThread(void *arg) { @@ -2090,7 +1910,6 @@ static void *GamepadThread(void *arg) return NULL; } -*/ // Search matching DRM mode in connector's mode list static int FindMatchingConnectorMode(const drmModeConnector *connector, const drmModeModeInfo *mode) diff --git a/src/rcore_template.c b/src/rcore_template.c index 3929de4b3..f74e7892f 100644 --- a/src/rcore_template.c +++ b/src/rcore_template.c @@ -571,7 +571,7 @@ void PollInputEvents(void) // Reset last gamepad button/axis registered state CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN - CORE.Input.Gamepad.axisCount = 0; + //CORE.Input.Gamepad.axisCount = 0; // Register previous touch states for (int i = 0; i < MAX_TOUCH_POINTS; i++) CORE.Input.Touch.previousTouchState[i] = CORE.Input.Touch.currentTouchState[i]; diff --git a/src/rcore_web.c b/src/rcore_web.c index 71e818ea8..68e236f60 100644 --- a/src/rcore_web.c +++ b/src/rcore_web.c @@ -706,7 +706,7 @@ void PollInputEvents(void) // Reset last gamepad button/axis registered state CORE.Input.Gamepad.lastButtonPressed = 0; // GAMEPAD_BUTTON_UNKNOWN - CORE.Input.Gamepad.axisCount = 0; + //CORE.Input.Gamepad.axisCount = 0; // Keyboard/Mouse input polling (automatically managed by GLFW3 through callback) // Register previous keys states @@ -800,7 +800,7 @@ void PollInputEvents(void) CORE.Input.Gamepad.axisState[i][j] = gamepadState.axis[j]; } - CORE.Input.Gamepad.axisCount = gamepadState.numAxes; + CORE.Input.Gamepad.axisCount[i] = gamepadState.numAxes; } } }