From 93a94eec2a99160e37e63b4396dc0e7403c2ae13 Mon Sep 17 00:00:00 2001 From: nymea Date: Wed, 21 Aug 2019 14:06:55 +0200 Subject: [PATCH] added missing files --- keyevent/devicepluginkeyevent.cpp | 76 +++++++++++++++++++++ keyevent/devicepluginkeyevent.h | 52 +++++++++++++++ keyevent/devicepluginkeyevent.json | 93 ++++++++++++++++++++++++++ keyevent/emitkeyevent.cpp | 102 +++++++++++++++++++++++++++++ keyevent/emitkeyevent.h | 44 +++++++++++++ keyevent/keyevent.pro | 17 +++++ keyevent/keymap.h | 11 ++++ keyevent/receivekeyevent.cpp | 30 +++++++++ keyevent/receivekeyevent.h | 22 +++++++ nymea-plugins.pro | 1 + 10 files changed, 448 insertions(+) create mode 100644 keyevent/devicepluginkeyevent.cpp create mode 100644 keyevent/devicepluginkeyevent.h create mode 100644 keyevent/devicepluginkeyevent.json create mode 100644 keyevent/emitkeyevent.cpp create mode 100644 keyevent/emitkeyevent.h create mode 100644 keyevent/keyevent.pro create mode 100644 keyevent/keymap.h create mode 100644 keyevent/receivekeyevent.cpp create mode 100644 keyevent/receivekeyevent.h diff --git a/keyevent/devicepluginkeyevent.cpp b/keyevent/devicepluginkeyevent.cpp new file mode 100644 index 00000000..42d0cd11 --- /dev/null +++ b/keyevent/devicepluginkeyevent.cpp @@ -0,0 +1,76 @@ +#include "devicepluginkeyevent.h" +#include "devices/device.h" +#include "plugininfo.h" + + +DevicePluginKeyEvent::DevicePluginKeyEvent() +{ +} + +Device::DeviceSetupStatus DevicePluginKeyEvent::setupDevice(Device *device) +{ + if(!m_keyEvent) { + m_keyEvent = new KeyEvent(this); + if (!m_keyEvent->create("Test")) { + return Device::DeviceSetupStatusFailure; + } + } + + if (device->deviceClassId() == keyEventDeviceClassId) { + return Device::DeviceSetupStatusSuccess; + } + return Device::DeviceSetupStatusFailure; +} + +void DevicePluginKeyEvent::deviceRemoved(Device *device) +{ + if (device->deviceClassId() == keyEventDeviceClassId) { + + } +} + +Device::DeviceError DevicePluginKeyEvent::executeAction(Device *device, const Action &action) +{ + if (device->deviceClassId() == keyEventDeviceClassId) { + + if (action.actionTypeId() == keyEventPlayActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_Play, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + if (action.actionTypeId() == keyEventPauseActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_Pause, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + if (action.actionTypeId() == keyEventStopActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_Stop, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + if (action.actionTypeId() == keyEventVolumeDownActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_VolumeDown, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + if (action.actionTypeId() == keyEventVolumeUpActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_VolumeUp, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + if (action.actionTypeId() == keyEventMuteActionTypeId) { + QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_VolumeMute, Qt::NoModifier); + + + return Device::DeviceErrorNoError; + } + + return Device::DeviceErrorActionTypeNotFound; + } + return Device::DeviceErrorDeviceClassNotFound; +} diff --git a/keyevent/devicepluginkeyevent.h b/keyevent/devicepluginkeyevent.h new file mode 100644 index 00000000..1a5b16cb --- /dev/null +++ b/keyevent/devicepluginkeyevent.h @@ -0,0 +1,52 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea 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 nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DEVICEPLUGINKEYEVENT_H +#define DEVICEPLUGINKEYEVENT_H + +#include "devices/deviceplugin.h" +#include "plugintimer.h" +#include "emitkeyevent.h" +#include "receivekeyevent.h" + +#include + +class DevicePluginKeyEvent : public DevicePlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "devicepluginkeyevent.json") + Q_INTERFACES(DevicePlugin) + +public: + explicit DevicePluginKeyEvent(); + + Device::DeviceSetupStatus setupDevice(Device *device) override; + void deviceRemoved(Device *device) override; + Device::DeviceError executeAction(Device *device, const Action &action) override; + +private: + EmitKeyEvent *m_keyEvent = nullptr; + +private slots: + +}; + +#endif // DEVICEPLUGINKEYEVENT_H diff --git a/keyevent/devicepluginkeyevent.json b/keyevent/devicepluginkeyevent.json new file mode 100644 index 00000000..0b161d5a --- /dev/null +++ b/keyevent/devicepluginkeyevent.json @@ -0,0 +1,93 @@ +{ + "displayName": "Key event", + "name": "keyEvent", + "id": "fe93a12e-36f4-4015-8019-26b659817773", + "vendors": [ + { + "name": "nymea", + "displayName": "nymea", + "id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6", + "deviceClasses": [ + { + "id": "d4d260a9-4b0e-41c7-93ff-02d4ac547a4d", + "name": "keyEvent", + "displayName": "Key event", + "createMethods": ["user"], + "interfaces": ["simplemultibutton", "mediacontroller"], + "paramTypes": [ + ], + "stateTypes": [ + ], + "actionTypes": [ + { + "id": "3171f6d7-d544-40b9-98c1-a06693dda6b5", + "name": "skipBack", + "displayName": "Skip back" + }, + { + "id": "3e56fc10-4fc3-445d-a14c-1e49948372c6", + "name": "fastRewind", + "displayName": "Rewind" + }, + { + "id": "3d6d3e04-275f-480d-954a-8f9b99ee63ad", + "name": "stop", + "displayName": "Stop" + }, + { + "id": "785c8487-9bed-4018-a551-af416119c685", + "name": "play", + "displayName": "Play" + }, + { + "id": "e39be594-3c4a-4935-96e9-c41b14191e39", + "name": "pause", + "displayName": "Pause" + }, + { + "id": "f9475947-9a79-43a4-8497-e22285a21141", + "name": "fastForward", + "displayName": "Fast forward" + }, + { + "id": "183c04ea-c3bc-422d-9156-d5ef5af8b78a", + "name": "skipNext", + "displayName": "Skip next" + }, + { + "id": "6b4cbd8a-719d-40ba-af1d-701d1ae870f7", + "name": "volumeUp", + "displayName": "Volume up" + }, + { + "id": "34f8a530-9164-4571-aaac-6d45c7abc8f9", + "name": "volumeDown", + "displayName": "Volume down" + }, + { + "id": "09a98f74-ad23-418c-b160-c0b88890bc4c", + "name": "mute", + "displayName": "Mute" + } + ], + "eventTypes": [ + { + "id": "c05c7ba9-e27a-45d8-8b0d-b8d7ceab2f5b", + "name": "pressed", + "displayName": "Key pressed", + "paramTypes": [ + { + "id": "427a25ec-f2bc-46c4-ad82-598d008293bd", + "name": "buttonName", + "displayName": "Key", + "type": "QString", + "defaultValue": "" + } + ] + } + ] + } + ] + } + ] +} diff --git a/keyevent/emitkeyevent.cpp b/keyevent/emitkeyevent.cpp new file mode 100644 index 00000000..149db772 --- /dev/null +++ b/keyevent/emitkeyevent.cpp @@ -0,0 +1,102 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea 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 nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "emitkeyevent.h" +#include "keymap.h" +#include "extern-plugininfo.h" + +#include +#include +#include +#include +#include + +EmitKeyEvent::EmitKeyEvent(QObject *parent) : QObject(parent) +{ + +} + +EmitKeyEvent::~EmitKeyEvent() +{ + ioctl(m_uinputFd, UI_DEV_DESTROY); + close(m_uinputFd); + m_uinputFd = -1; +} + +bool EmitKeyEvent::init() +{ + m_uinputFd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (m_uinputFd == -1) { + qWarning(dcKeyEvent) << "Failed to open '/dev/uinput'"; + return false; + } + + /*foreach (Qt::Key key, Qt->idKeyMap.keys().toSet()) { + if (ioctl(m_uinputFd, UI_SET_EVBIT, EV_KEY) < 0) { + qWarning(dcKeyEvent) << "Failed to enable keys for the uinput device"; + return false; + } + + if (ioctl(m_uinputFd, UI_SET_KEYBIT, d->qtKeyToUiKey(key)) < 0) { + qWarning(dcKeyEvent) << "Failed to enable Qt key" << key; + return false; + } + }*/ + + uinput_user_dev uidev; + memset(&uidev, 0, sizeof(uidev)); + snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "nymea"); + uidev.id.bustype = BUS_VIRTUAL; + uidev.id.vendor = 0x00; + uidev.id.product = 0x00; + uidev.id.version = 0x01; + if (write(m_uinputFd, &uidev, sizeof(uidev)) != sizeof(uidev)) { + qWarning(dcKeyEvent) << "Failed to write device information to uinput"; + return false; + } + + if (ioctl( m_uinputFd, UI_DEV_CREATE) < 0) { + qWarning(dcKeyEvent) << "Failed to create uinput device"; + return false; + } + + return true; +} + +bool EmitKeyEvent::sendKeyEvent(Qt::Key key, bool pressed) +{ + + if (m_uinputFd == -1) { + qWarning(dcKeyEvent()) << "Cannot send key event, device has not been created"; + return false; + } + + struct input_event ev; + memset(&ev, 0, sizeof(ev)); + ev.type = EV_KEY; + ev.code = key; + ev.value = pressed; + if (write(m_uinputFd, &ev, sizeof(ev)) != sizeof(ev)) { + qWarning(dcKeyEvent()) << "Cannot write input event to uintput"; + return false; + } + qDebug(dcKeyEvent()) << "key event sent to uinput device succesfully"; + return true; +} diff --git a/keyevent/emitkeyevent.h b/keyevent/emitkeyevent.h new file mode 100644 index 00000000..5e65d96e --- /dev/null +++ b/keyevent/emitkeyevent.h @@ -0,0 +1,44 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Bernhard Trinnes * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea 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 nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef EMITKEYEVENT_H +#define EMITKEYEVENT_H + +#include + +class EmitKeyEvent : public QObject +{ + Q_OBJECT +public: + explicit EmitKeyEvent(QObject *parent = nullptr); + ~EmitKeyEvent(); + + bool init(); + bool sendKeyEvent(Qt::Key key, bool pressed); + +private: + int m_uinputFd = -1; + +signals: + +public slots: +}; + +#endif // EMITKEYEVENT_H diff --git a/keyevent/keyevent.pro b/keyevent/keyevent.pro new file mode 100644 index 00000000..fe7be938 --- /dev/null +++ b/keyevent/keyevent.pro @@ -0,0 +1,17 @@ +include(../plugins.pri) + +#QT += gui + +TARGET = $$qtLibraryTarget(nymea_devicepluginkeyevent) + +SOURCES += \ + devicepluginkeyevent.cpp \ + emitkeyevent.cpp \ + receivekeyevent.cpp + +HEADERS += \ + devicepluginkeyevent.h \ + emitkeyevent.h \ + keymap.h \ + receivekeyevent.h + diff --git a/keyevent/keymap.h b/keyevent/keymap.h new file mode 100644 index 00000000..4ed88818 --- /dev/null +++ b/keyevent/keymap.h @@ -0,0 +1,11 @@ +#ifndef KEYMAP_H +#define KEYMAP_H + +#include +#include + +QMap keyMap; +//Qt::Key::Key_Play; +//keyMap[Qt::Key_Play] = KEY_PLAY; + +#endif // KEYMAP_H diff --git a/keyevent/receivekeyevent.cpp b/keyevent/receivekeyevent.cpp new file mode 100644 index 00000000..c15fa245 --- /dev/null +++ b/keyevent/receivekeyevent.cpp @@ -0,0 +1,30 @@ +#include "receivekeyevent.h" +#include "extern-plugininfo.h" + +#include +#include +#include + +#include + +ReceiveKeyEvent::ReceiveKeyEvent(QObject *parent) : QObject(parent) +{ + +} + +bool ReceiveKeyEvent::init() +{ + QString dev = QLatin1String("/dev/input/event1"); + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0); + if (m_fd == -1) { + qWarning(dcKeyEvent) << "Cannot open input device" << dev << strerror(errno); + return false; + } + + ioctl(m_fd, EVIOCSREP, kbdrep); + + QSocketNotifier *notifier; + notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode())); +} + diff --git a/keyevent/receivekeyevent.h b/keyevent/receivekeyevent.h new file mode 100644 index 00000000..75d6799f --- /dev/null +++ b/keyevent/receivekeyevent.h @@ -0,0 +1,22 @@ +#ifndef RECEIVEKEYEVENT_H +#define RECEIVEKEYEVENT_H + +#include + +class ReceiveKeyEvent : public QObject +{ + Q_OBJECT +public: + explicit ReceiveKeyEvent(QObject *parent = nullptr); + bool init(); + +private: + int m_fd; + +signals: + void keyEventReceived(Qt::Key key, bool pressed); + void longPressed(Qt::Key key); + void doublePressed(Qt::Key key); +}; + +#endif // RECEIVEKEYEVENT_H diff --git a/nymea-plugins.pro b/nymea-plugins.pro index 8985227c..7ea274c2 100644 --- a/nymea-plugins.pro +++ b/nymea-plugins.pro @@ -20,6 +20,7 @@ PLUGIN_DIRS = \ httpcommander \ intertechno \ keba \ + keyevent \ kodi \ leynew \ lgsmarttv \