File indexing completed on 2024-04-21 16:11:00
0001 /* 0002 * SPDX-FileCopyrightText: 2022 Bart Ribbers <bribbers@disroot.org> 0003 * SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez <aleixpol@kde.org> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #include "uinputsystem.h" 0009 0010 #include <linux/uinput.h> 0011 #include <fcntl.h> 0012 #include <unistd.h> 0013 0014 #include <QDebug> 0015 0016 UInputSystem::UInputSystem() 0017 { 0018 } 0019 0020 bool UInputSystem::init() 0021 { 0022 setSupportedKeys({}); 0023 return m_fd > 0; 0024 } 0025 0026 void UInputSystem::emitKey(int key, bool pressed) 0027 { 0028 if (!m_supportedKeys.contains(key)) { 0029 qWarning() << "reporting unannounced key" << key; 0030 } 0031 qWarning() << "key" << key << pressed; 0032 emitEvent(EV_KEY, key, pressed ? 1 : 0); 0033 emitEvent(EV_SYN, SYN_REPORT, 0); 0034 } 0035 0036 void UInputSystem::emitEvent(int type, int code, int val) 0037 { 0038 struct input_event ie; 0039 0040 ie.type = type; 0041 ie.code = code; 0042 ie.value = val; 0043 ie.input_event_sec = 0; 0044 ie.input_event_usec = 0; 0045 0046 write(m_fd, &ie, sizeof(ie)); 0047 } 0048 0049 void UInputSystem::setSupportedKeys(const QSet<int>& keys) 0050 { 0051 if (m_fd > 0 && keys == m_supportedKeys) { 0052 return; 0053 } 0054 if (m_fd > 0) { 0055 close(m_fd); 0056 } 0057 0058 m_supportedKeys = keys; 0059 0060 struct uinput_setup usetup; 0061 m_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); 0062 0063 if (m_fd < 0) { 0064 qCritical() << "Couldn't open /dev/uinput, make sure the kernel module is loaded"; 0065 return; 0066 } 0067 0068 // Register all keys we want to press with this application 0069 ioctl(m_fd, UI_SET_EVBIT, EV_KEY); 0070 0071 for ( auto x : std::as_const(m_supportedKeys)) 0072 ioctl(m_fd, UI_SET_KEYBIT, x); 0073 0074 memset(&usetup, 0, sizeof(usetup)); 0075 usetup.id.bustype = BUS_USB; 0076 usetup.id.vendor = 0x1234; // TODO: change vendor 0077 usetup.id.product = 0x5678; // TODO: change product 0078 strcpy(usetup.name, "PlasmaRemoteControllers"); 0079 0080 ioctl(m_fd, UI_DEV_SETUP, &usetup); 0081 ioctl(m_fd, UI_DEV_CREATE); 0082 }