1b877906bSopenharmony_ci//======================================================================== 2b877906bSopenharmony_ci// GLFW 3.5 Linux - www.glfw.org 3b877906bSopenharmony_ci//------------------------------------------------------------------------ 4b877906bSopenharmony_ci// Copyright (c) 2002-2006 Marcus Geelnard 5b877906bSopenharmony_ci// Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org> 6b877906bSopenharmony_ci// 7b877906bSopenharmony_ci// This software is provided 'as-is', without any express or implied 8b877906bSopenharmony_ci// warranty. In no event will the authors be held liable for any damages 9b877906bSopenharmony_ci// arising from the use of this software. 10b877906bSopenharmony_ci// 11b877906bSopenharmony_ci// Permission is granted to anyone to use this software for any purpose, 12b877906bSopenharmony_ci// including commercial applications, and to alter it and redistribute it 13b877906bSopenharmony_ci// freely, subject to the following restrictions: 14b877906bSopenharmony_ci// 15b877906bSopenharmony_ci// 1. The origin of this software must not be misrepresented; you must not 16b877906bSopenharmony_ci// claim that you wrote the original software. If you use this software 17b877906bSopenharmony_ci// in a product, an acknowledgment in the product documentation would 18b877906bSopenharmony_ci// be appreciated but is not required. 19b877906bSopenharmony_ci// 20b877906bSopenharmony_ci// 2. Altered source versions must be plainly marked as such, and must not 21b877906bSopenharmony_ci// be misrepresented as being the original software. 22b877906bSopenharmony_ci// 23b877906bSopenharmony_ci// 3. This notice may not be removed or altered from any source 24b877906bSopenharmony_ci// distribution. 25b877906bSopenharmony_ci// 26b877906bSopenharmony_ci//======================================================================== 27b877906bSopenharmony_ci 28b877906bSopenharmony_ci#include "internal.h" 29b877906bSopenharmony_ci 30b877906bSopenharmony_ci#if defined(GLFW_BUILD_LINUX_JOYSTICK) 31b877906bSopenharmony_ci 32b877906bSopenharmony_ci#include <sys/types.h> 33b877906bSopenharmony_ci#include <sys/stat.h> 34b877906bSopenharmony_ci#include <sys/inotify.h> 35b877906bSopenharmony_ci#include <fcntl.h> 36b877906bSopenharmony_ci#include <errno.h> 37b877906bSopenharmony_ci#include <dirent.h> 38b877906bSopenharmony_ci#include <stdio.h> 39b877906bSopenharmony_ci#include <stdlib.h> 40b877906bSopenharmony_ci#include <string.h> 41b877906bSopenharmony_ci#include <unistd.h> 42b877906bSopenharmony_ci 43b877906bSopenharmony_ci#ifndef SYN_DROPPED // < v2.6.39 kernel headers 44b877906bSopenharmony_ci// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32 45b877906bSopenharmony_ci#define SYN_DROPPED 3 46b877906bSopenharmony_ci#endif 47b877906bSopenharmony_ci 48b877906bSopenharmony_ci// Apply an EV_KEY event to the specified joystick 49b877906bSopenharmony_ci// 50b877906bSopenharmony_cistatic void handleKeyEvent(_GLFWjoystick* js, int code, int value) 51b877906bSopenharmony_ci{ 52b877906bSopenharmony_ci _glfwInputJoystickButton(js, 53b877906bSopenharmony_ci js->linjs.keyMap[code - BTN_MISC], 54b877906bSopenharmony_ci value ? GLFW_PRESS : GLFW_RELEASE); 55b877906bSopenharmony_ci} 56b877906bSopenharmony_ci 57b877906bSopenharmony_ci// Apply an EV_ABS event to the specified joystick 58b877906bSopenharmony_ci// 59b877906bSopenharmony_cistatic void handleAbsEvent(_GLFWjoystick* js, int code, int value) 60b877906bSopenharmony_ci{ 61b877906bSopenharmony_ci const int index = js->linjs.absMap[code]; 62b877906bSopenharmony_ci 63b877906bSopenharmony_ci if (code >= ABS_HAT0X && code <= ABS_HAT3Y) 64b877906bSopenharmony_ci { 65b877906bSopenharmony_ci static const char stateMap[3][3] = 66b877906bSopenharmony_ci { 67b877906bSopenharmony_ci { GLFW_HAT_CENTERED, GLFW_HAT_UP, GLFW_HAT_DOWN }, 68b877906bSopenharmony_ci { GLFW_HAT_LEFT, GLFW_HAT_LEFT_UP, GLFW_HAT_LEFT_DOWN }, 69b877906bSopenharmony_ci { GLFW_HAT_RIGHT, GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN }, 70b877906bSopenharmony_ci }; 71b877906bSopenharmony_ci 72b877906bSopenharmony_ci const int hat = (code - ABS_HAT0X) / 2; 73b877906bSopenharmony_ci const int axis = (code - ABS_HAT0X) % 2; 74b877906bSopenharmony_ci int* state = js->linjs.hats[hat]; 75b877906bSopenharmony_ci 76b877906bSopenharmony_ci // NOTE: Looking at several input drivers, it seems all hat events use 77b877906bSopenharmony_ci // -1 for left / up, 0 for centered and 1 for right / down 78b877906bSopenharmony_ci if (value == 0) 79b877906bSopenharmony_ci state[axis] = 0; 80b877906bSopenharmony_ci else if (value < 0) 81b877906bSopenharmony_ci state[axis] = 1; 82b877906bSopenharmony_ci else if (value > 0) 83b877906bSopenharmony_ci state[axis] = 2; 84b877906bSopenharmony_ci 85b877906bSopenharmony_ci _glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]); 86b877906bSopenharmony_ci } 87b877906bSopenharmony_ci else 88b877906bSopenharmony_ci { 89b877906bSopenharmony_ci const struct input_absinfo* info = &js->linjs.absInfo[code]; 90b877906bSopenharmony_ci float normalized = value; 91b877906bSopenharmony_ci 92b877906bSopenharmony_ci const int range = info->maximum - info->minimum; 93b877906bSopenharmony_ci if (range) 94b877906bSopenharmony_ci { 95b877906bSopenharmony_ci // Normalize to 0.0 -> 1.0 96b877906bSopenharmony_ci normalized = (normalized - info->minimum) / range; 97b877906bSopenharmony_ci // Normalize to -1.0 -> 1.0 98b877906bSopenharmony_ci normalized = normalized * 2.0f - 1.0f; 99b877906bSopenharmony_ci } 100b877906bSopenharmony_ci 101b877906bSopenharmony_ci _glfwInputJoystickAxis(js, index, normalized); 102b877906bSopenharmony_ci } 103b877906bSopenharmony_ci} 104b877906bSopenharmony_ci 105b877906bSopenharmony_ci// Poll state of absolute axes 106b877906bSopenharmony_ci// 107b877906bSopenharmony_cistatic void pollAbsState(_GLFWjoystick* js) 108b877906bSopenharmony_ci{ 109b877906bSopenharmony_ci for (int code = 0; code < ABS_CNT; code++) 110b877906bSopenharmony_ci { 111b877906bSopenharmony_ci if (js->linjs.absMap[code] < 0) 112b877906bSopenharmony_ci continue; 113b877906bSopenharmony_ci 114b877906bSopenharmony_ci struct input_absinfo* info = &js->linjs.absInfo[code]; 115b877906bSopenharmony_ci 116b877906bSopenharmony_ci if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0) 117b877906bSopenharmony_ci continue; 118b877906bSopenharmony_ci 119b877906bSopenharmony_ci handleAbsEvent(js, code, info->value); 120b877906bSopenharmony_ci } 121b877906bSopenharmony_ci} 122b877906bSopenharmony_ci 123b877906bSopenharmony_ci#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8))) 124b877906bSopenharmony_ci 125b877906bSopenharmony_ci// Attempt to open the specified joystick device 126b877906bSopenharmony_ci// 127b877906bSopenharmony_cistatic GLFWbool openJoystickDevice(const char* path) 128b877906bSopenharmony_ci{ 129b877906bSopenharmony_ci for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) 130b877906bSopenharmony_ci { 131b877906bSopenharmony_ci if (!_glfw.joysticks[jid].connected) 132b877906bSopenharmony_ci continue; 133b877906bSopenharmony_ci if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) 134b877906bSopenharmony_ci return GLFW_FALSE; 135b877906bSopenharmony_ci } 136b877906bSopenharmony_ci 137b877906bSopenharmony_ci _GLFWjoystickLinux linjs = {0}; 138b877906bSopenharmony_ci linjs.fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); 139b877906bSopenharmony_ci if (linjs.fd == -1) 140b877906bSopenharmony_ci return GLFW_FALSE; 141b877906bSopenharmony_ci 142b877906bSopenharmony_ci char evBits[(EV_CNT + 7) / 8] = {0}; 143b877906bSopenharmony_ci char keyBits[(KEY_CNT + 7) / 8] = {0}; 144b877906bSopenharmony_ci char absBits[(ABS_CNT + 7) / 8] = {0}; 145b877906bSopenharmony_ci struct input_id id; 146b877906bSopenharmony_ci 147b877906bSopenharmony_ci if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 || 148b877906bSopenharmony_ci ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 || 149b877906bSopenharmony_ci ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 || 150b877906bSopenharmony_ci ioctl(linjs.fd, EVIOCGID, &id) < 0) 151b877906bSopenharmony_ci { 152b877906bSopenharmony_ci _glfwInputError(GLFW_PLATFORM_ERROR, 153b877906bSopenharmony_ci "Linux: Failed to query input device: %s", 154b877906bSopenharmony_ci strerror(errno)); 155b877906bSopenharmony_ci close(linjs.fd); 156b877906bSopenharmony_ci return GLFW_FALSE; 157b877906bSopenharmony_ci } 158b877906bSopenharmony_ci 159b877906bSopenharmony_ci // Ensure this device supports the events expected of a joystick 160b877906bSopenharmony_ci if (!isBitSet(EV_ABS, evBits)) 161b877906bSopenharmony_ci { 162b877906bSopenharmony_ci close(linjs.fd); 163b877906bSopenharmony_ci return GLFW_FALSE; 164b877906bSopenharmony_ci } 165b877906bSopenharmony_ci 166b877906bSopenharmony_ci char name[256] = ""; 167b877906bSopenharmony_ci 168b877906bSopenharmony_ci if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0) 169b877906bSopenharmony_ci strncpy(name, "Unknown", sizeof(name)); 170b877906bSopenharmony_ci 171b877906bSopenharmony_ci char guid[33] = ""; 172b877906bSopenharmony_ci 173b877906bSopenharmony_ci // Generate a joystick GUID that matches the SDL 2.0.5+ one 174b877906bSopenharmony_ci if (id.vendor && id.product && id.version) 175b877906bSopenharmony_ci { 176b877906bSopenharmony_ci sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000", 177b877906bSopenharmony_ci id.bustype & 0xff, id.bustype >> 8, 178b877906bSopenharmony_ci id.vendor & 0xff, id.vendor >> 8, 179b877906bSopenharmony_ci id.product & 0xff, id.product >> 8, 180b877906bSopenharmony_ci id.version & 0xff, id.version >> 8); 181b877906bSopenharmony_ci } 182b877906bSopenharmony_ci else 183b877906bSopenharmony_ci { 184b877906bSopenharmony_ci sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00", 185b877906bSopenharmony_ci id.bustype & 0xff, id.bustype >> 8, 186b877906bSopenharmony_ci name[0], name[1], name[2], name[3], 187b877906bSopenharmony_ci name[4], name[5], name[6], name[7], 188b877906bSopenharmony_ci name[8], name[9], name[10]); 189b877906bSopenharmony_ci } 190b877906bSopenharmony_ci 191b877906bSopenharmony_ci int axisCount = 0, buttonCount = 0, hatCount = 0; 192b877906bSopenharmony_ci 193b877906bSopenharmony_ci for (int code = BTN_MISC; code < KEY_CNT; code++) 194b877906bSopenharmony_ci { 195b877906bSopenharmony_ci if (!isBitSet(code, keyBits)) 196b877906bSopenharmony_ci continue; 197b877906bSopenharmony_ci 198b877906bSopenharmony_ci linjs.keyMap[code - BTN_MISC] = buttonCount; 199b877906bSopenharmony_ci buttonCount++; 200b877906bSopenharmony_ci } 201b877906bSopenharmony_ci 202b877906bSopenharmony_ci for (int code = 0; code < ABS_CNT; code++) 203b877906bSopenharmony_ci { 204b877906bSopenharmony_ci linjs.absMap[code] = -1; 205b877906bSopenharmony_ci if (!isBitSet(code, absBits)) 206b877906bSopenharmony_ci continue; 207b877906bSopenharmony_ci 208b877906bSopenharmony_ci if (code >= ABS_HAT0X && code <= ABS_HAT3Y) 209b877906bSopenharmony_ci { 210b877906bSopenharmony_ci linjs.absMap[code] = hatCount; 211b877906bSopenharmony_ci hatCount++; 212b877906bSopenharmony_ci // Skip the Y axis 213b877906bSopenharmony_ci code++; 214b877906bSopenharmony_ci } 215b877906bSopenharmony_ci else 216b877906bSopenharmony_ci { 217b877906bSopenharmony_ci if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0) 218b877906bSopenharmony_ci continue; 219b877906bSopenharmony_ci 220b877906bSopenharmony_ci linjs.absMap[code] = axisCount; 221b877906bSopenharmony_ci axisCount++; 222b877906bSopenharmony_ci } 223b877906bSopenharmony_ci } 224b877906bSopenharmony_ci 225b877906bSopenharmony_ci _GLFWjoystick* js = 226b877906bSopenharmony_ci _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount); 227b877906bSopenharmony_ci if (!js) 228b877906bSopenharmony_ci { 229b877906bSopenharmony_ci close(linjs.fd); 230b877906bSopenharmony_ci return GLFW_FALSE; 231b877906bSopenharmony_ci } 232b877906bSopenharmony_ci 233b877906bSopenharmony_ci strncpy(linjs.path, path, sizeof(linjs.path) - 1); 234b877906bSopenharmony_ci memcpy(&js->linjs, &linjs, sizeof(linjs)); 235b877906bSopenharmony_ci 236b877906bSopenharmony_ci pollAbsState(js); 237b877906bSopenharmony_ci 238b877906bSopenharmony_ci _glfwInputJoystick(js, GLFW_CONNECTED); 239b877906bSopenharmony_ci return GLFW_TRUE; 240b877906bSopenharmony_ci} 241b877906bSopenharmony_ci 242b877906bSopenharmony_ci#undef isBitSet 243b877906bSopenharmony_ci 244b877906bSopenharmony_ci// Frees all resources associated with the specified joystick 245b877906bSopenharmony_ci// 246b877906bSopenharmony_cistatic void closeJoystick(_GLFWjoystick* js) 247b877906bSopenharmony_ci{ 248b877906bSopenharmony_ci _glfwInputJoystick(js, GLFW_DISCONNECTED); 249b877906bSopenharmony_ci close(js->linjs.fd); 250b877906bSopenharmony_ci _glfwFreeJoystick(js); 251b877906bSopenharmony_ci} 252b877906bSopenharmony_ci 253b877906bSopenharmony_ci// Lexically compare joysticks by name; used by qsort 254b877906bSopenharmony_ci// 255b877906bSopenharmony_cistatic int compareJoysticks(const void* fp, const void* sp) 256b877906bSopenharmony_ci{ 257b877906bSopenharmony_ci const _GLFWjoystick* fj = fp; 258b877906bSopenharmony_ci const _GLFWjoystick* sj = sp; 259b877906bSopenharmony_ci return strcmp(fj->linjs.path, sj->linjs.path); 260b877906bSopenharmony_ci} 261b877906bSopenharmony_ci 262b877906bSopenharmony_ci 263b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 264b877906bSopenharmony_ci////// GLFW internal API ////// 265b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 266b877906bSopenharmony_ci 267b877906bSopenharmony_civoid _glfwDetectJoystickConnectionLinux(void) 268b877906bSopenharmony_ci{ 269b877906bSopenharmony_ci if (_glfw.linjs.inotify <= 0) 270b877906bSopenharmony_ci return; 271b877906bSopenharmony_ci 272b877906bSopenharmony_ci ssize_t offset = 0; 273b877906bSopenharmony_ci char buffer[16384]; 274b877906bSopenharmony_ci const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); 275b877906bSopenharmony_ci 276b877906bSopenharmony_ci while (size > offset) 277b877906bSopenharmony_ci { 278b877906bSopenharmony_ci regmatch_t match; 279b877906bSopenharmony_ci const struct inotify_event* e = (struct inotify_event*) (buffer + offset); 280b877906bSopenharmony_ci 281b877906bSopenharmony_ci offset += sizeof(struct inotify_event) + e->len; 282b877906bSopenharmony_ci 283b877906bSopenharmony_ci if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0) 284b877906bSopenharmony_ci continue; 285b877906bSopenharmony_ci 286b877906bSopenharmony_ci char path[PATH_MAX]; 287b877906bSopenharmony_ci snprintf(path, sizeof(path), "/dev/input/%s", e->name); 288b877906bSopenharmony_ci 289b877906bSopenharmony_ci if (e->mask & (IN_CREATE | IN_ATTRIB)) 290b877906bSopenharmony_ci openJoystickDevice(path); 291b877906bSopenharmony_ci else if (e->mask & IN_DELETE) 292b877906bSopenharmony_ci { 293b877906bSopenharmony_ci for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) 294b877906bSopenharmony_ci { 295b877906bSopenharmony_ci if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) 296b877906bSopenharmony_ci { 297b877906bSopenharmony_ci closeJoystick(_glfw.joysticks + jid); 298b877906bSopenharmony_ci break; 299b877906bSopenharmony_ci } 300b877906bSopenharmony_ci } 301b877906bSopenharmony_ci } 302b877906bSopenharmony_ci } 303b877906bSopenharmony_ci} 304b877906bSopenharmony_ci 305b877906bSopenharmony_ci 306b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 307b877906bSopenharmony_ci////// GLFW platform API ////// 308b877906bSopenharmony_ci////////////////////////////////////////////////////////////////////////// 309b877906bSopenharmony_ci 310b877906bSopenharmony_ciGLFWbool _glfwInitJoysticksLinux(void) 311b877906bSopenharmony_ci{ 312b877906bSopenharmony_ci const char* dirname = "/dev/input"; 313b877906bSopenharmony_ci 314b877906bSopenharmony_ci _glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); 315b877906bSopenharmony_ci if (_glfw.linjs.inotify > 0) 316b877906bSopenharmony_ci { 317b877906bSopenharmony_ci // HACK: Register for IN_ATTRIB to get notified when udev is done 318b877906bSopenharmony_ci // This works well in practice but the true way is libudev 319b877906bSopenharmony_ci 320b877906bSopenharmony_ci _glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify, 321b877906bSopenharmony_ci dirname, 322b877906bSopenharmony_ci IN_CREATE | IN_ATTRIB | IN_DELETE); 323b877906bSopenharmony_ci } 324b877906bSopenharmony_ci 325b877906bSopenharmony_ci // Continue without device connection notifications if inotify fails 326b877906bSopenharmony_ci 327b877906bSopenharmony_ci _glfw.linjs.regexCompiled = (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) == 0); 328b877906bSopenharmony_ci if (!_glfw.linjs.regexCompiled) 329b877906bSopenharmony_ci { 330b877906bSopenharmony_ci _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex"); 331b877906bSopenharmony_ci return GLFW_FALSE; 332b877906bSopenharmony_ci } 333b877906bSopenharmony_ci 334b877906bSopenharmony_ci int count = 0; 335b877906bSopenharmony_ci 336b877906bSopenharmony_ci DIR* dir = opendir(dirname); 337b877906bSopenharmony_ci if (dir) 338b877906bSopenharmony_ci { 339b877906bSopenharmony_ci struct dirent* entry; 340b877906bSopenharmony_ci 341b877906bSopenharmony_ci while ((entry = readdir(dir))) 342b877906bSopenharmony_ci { 343b877906bSopenharmony_ci regmatch_t match; 344b877906bSopenharmony_ci 345b877906bSopenharmony_ci if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0) 346b877906bSopenharmony_ci continue; 347b877906bSopenharmony_ci 348b877906bSopenharmony_ci char path[PATH_MAX]; 349b877906bSopenharmony_ci 350b877906bSopenharmony_ci snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name); 351b877906bSopenharmony_ci 352b877906bSopenharmony_ci if (openJoystickDevice(path)) 353b877906bSopenharmony_ci count++; 354b877906bSopenharmony_ci } 355b877906bSopenharmony_ci 356b877906bSopenharmony_ci closedir(dir); 357b877906bSopenharmony_ci } 358b877906bSopenharmony_ci 359b877906bSopenharmony_ci // Continue with no joysticks if enumeration fails 360b877906bSopenharmony_ci 361b877906bSopenharmony_ci qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks); 362b877906bSopenharmony_ci return GLFW_TRUE; 363b877906bSopenharmony_ci} 364b877906bSopenharmony_ci 365b877906bSopenharmony_civoid _glfwTerminateJoysticksLinux(void) 366b877906bSopenharmony_ci{ 367b877906bSopenharmony_ci for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) 368b877906bSopenharmony_ci { 369b877906bSopenharmony_ci _GLFWjoystick* js = _glfw.joysticks + jid; 370b877906bSopenharmony_ci if (js->connected) 371b877906bSopenharmony_ci closeJoystick(js); 372b877906bSopenharmony_ci } 373b877906bSopenharmony_ci 374b877906bSopenharmony_ci if (_glfw.linjs.inotify > 0) 375b877906bSopenharmony_ci { 376b877906bSopenharmony_ci if (_glfw.linjs.watch > 0) 377b877906bSopenharmony_ci inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch); 378b877906bSopenharmony_ci 379b877906bSopenharmony_ci close(_glfw.linjs.inotify); 380b877906bSopenharmony_ci } 381b877906bSopenharmony_ci 382b877906bSopenharmony_ci if (_glfw.linjs.regexCompiled) 383b877906bSopenharmony_ci regfree(&_glfw.linjs.regex); 384b877906bSopenharmony_ci} 385b877906bSopenharmony_ci 386b877906bSopenharmony_ciGLFWbool _glfwPollJoystickLinux(_GLFWjoystick* js, int mode) 387b877906bSopenharmony_ci{ 388b877906bSopenharmony_ci // Read all queued events (non-blocking) 389b877906bSopenharmony_ci for (;;) 390b877906bSopenharmony_ci { 391b877906bSopenharmony_ci struct input_event e; 392b877906bSopenharmony_ci 393b877906bSopenharmony_ci errno = 0; 394b877906bSopenharmony_ci if (read(js->linjs.fd, &e, sizeof(e)) < 0) 395b877906bSopenharmony_ci { 396b877906bSopenharmony_ci // Reset the joystick slot if the device was disconnected 397b877906bSopenharmony_ci if (errno == ENODEV) 398b877906bSopenharmony_ci closeJoystick(js); 399b877906bSopenharmony_ci 400b877906bSopenharmony_ci break; 401b877906bSopenharmony_ci } 402b877906bSopenharmony_ci 403b877906bSopenharmony_ci if (e.type == EV_SYN) 404b877906bSopenharmony_ci { 405b877906bSopenharmony_ci if (e.code == SYN_DROPPED) 406b877906bSopenharmony_ci _glfw.linjs.dropped = GLFW_TRUE; 407b877906bSopenharmony_ci else if (e.code == SYN_REPORT) 408b877906bSopenharmony_ci { 409b877906bSopenharmony_ci _glfw.linjs.dropped = GLFW_FALSE; 410b877906bSopenharmony_ci pollAbsState(js); 411b877906bSopenharmony_ci } 412b877906bSopenharmony_ci } 413b877906bSopenharmony_ci 414b877906bSopenharmony_ci if (_glfw.linjs.dropped) 415b877906bSopenharmony_ci continue; 416b877906bSopenharmony_ci 417b877906bSopenharmony_ci if (e.type == EV_KEY) 418b877906bSopenharmony_ci handleKeyEvent(js, e.code, e.value); 419b877906bSopenharmony_ci else if (e.type == EV_ABS) 420b877906bSopenharmony_ci handleAbsEvent(js, e.code, e.value); 421b877906bSopenharmony_ci } 422b877906bSopenharmony_ci 423b877906bSopenharmony_ci return js->connected; 424b877906bSopenharmony_ci} 425b877906bSopenharmony_ci 426b877906bSopenharmony_ciconst char* _glfwGetMappingNameLinux(void) 427b877906bSopenharmony_ci{ 428b877906bSopenharmony_ci return "Linux"; 429b877906bSopenharmony_ci} 430b877906bSopenharmony_ci 431b877906bSopenharmony_civoid _glfwUpdateGamepadGUIDLinux(char* guid) 432b877906bSopenharmony_ci{ 433b877906bSopenharmony_ci} 434b877906bSopenharmony_ci 435b877906bSopenharmony_ci#endif // GLFW_BUILD_LINUX_JOYSTICK 436b877906bSopenharmony_ci 437