diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml deleted file mode 100644 index a46e6842f..000000000 --- a/.github/workflows/nix.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Build with Nix - -on: - push: - branches: - - master - paths: - - 'applications/**' - - 'shared/**' - - 'assets/**' - - 'interfaces/**' - - 'qmake/**' - - 'oxide.pro' - - 'Makefile' - - '*.nix' - pull_request: - paths: - - 'applications/**' - - 'shared/**' - - 'assets/**' - - 'interfaces/**' - - 'qmake/**' - - 'oxide.pro' - - 'Makefile' - - '*.nix' -jobs: - nix-build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: cachix/install-nix-action@v20 - with: - nix_path: nixpkgs=channel:nixos-unstable - - uses: cachix/cachix-action@v12 - with: - name: nix-remarkable - authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - name: Build - run: nix-build --argstr system 'x86_64-linux' - timeout-minutes: 15 - - run: | - mkdir output - cp -a result/. output/ - - name: Save Artifact - uses: actions/upload-artifact@v3 - with: - name: output - path: output diff --git a/README.md b/README.md index 1df91e8c3..b5a002afe 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,3 @@ You can find other (likely outdated) [videos here](https://github.com/Eeems/oxid 1. Install [toltecmk](https://pypi.org/project/toltecmk/) 2. Run `make package` 3. The ipk files can be found in the `dist/` folder - -### Nix -Works on x86_64-linux or macOS via [nix-docker](https://github.com/LnL7/nix-docker). - -```ShellSession -$ nix-build --argstr system 'x86_64-linux' -``` diff --git a/applications/inject_evdev/main.cpp b/applications/inject_evdev/main.cpp index f29b9047f..452c409bd 100644 --- a/applications/inject_evdev/main.cpp +++ b/applications/inject_evdev/main.cpp @@ -82,9 +82,9 @@ bool process_EV_ABS(const QStringList& args){ abs(ABS_TILT_Y); abs(ABS_TOOL_WIDTH); abs(ABS_VOLUME); - //abs(ABS_PROFILE); + // abs(ABS_PROFILE); abs(ABS_MISC); - //abs(ABS_RESERVED); + abs(ABS_RESERVED); abs(ABS_MT_SLOT); abs(ABS_MT_TOUCH_MAJOR); abs(ABS_MT_TOUCH_MINOR); @@ -128,9 +128,9 @@ bool process_EV_REL(const QStringList& args){ rel(REL_DIAL); rel(REL_WHEEL); rel(REL_MISC); - //rel(REL_RESERVED); - //rel(REL_WHEEL_HI_RES); - //rel(REL_HWHEEL_HI_RES); + rel(REL_RESERVED); + rel(REL_WHEEL_HI_RES); + rel(REL_HWHEEL_HI_RES); rel(REL_MAX); rel(REL_CNT); qDebug() << "Unknown EV_REL event code:" << code.c_str(); @@ -350,7 +350,7 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_PAUSECD); key(KEY_PROG3); key(KEY_PROG4); - //key(KEY_ALL_APPLICATIONS); + // key(KEY_ALL_APPLICATIONS); key(KEY_DASHBOARD); key(KEY_SUSPEND); key(KEY_CLOSE); @@ -418,11 +418,11 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_TITLE); key(KEY_SUBTITLE); key(KEY_ANGLE); - //key(KEY_FULL_SCREEN); + key(KEY_FULL_SCREEN); key(KEY_ZOOM); key(KEY_MODE); key(KEY_KEYBOARD); - //key(KEY_ASPECT_RATIO); + key(KEY_ASPECT_RATIO); key(KEY_SCREEN); key(KEY_PC); key(KEY_TV); @@ -492,9 +492,9 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_10CHANNELSUP); key(KEY_10CHANNELSDOWN); key(KEY_IMAGES); - //key(KEY_NOTIFICATION_CENTER); - //key(KEY_PICKUP_PHONE); - //key(KEY_HANGUP_PHONE); + // key(KEY_NOTIFICATION_CENTER); + // key(KEY_PICKUP_PHONE); + // key(KEY_HANGUP_PHONE); key(KEY_DEL_EOL); key(KEY_DEL_EOS); key(KEY_INS_LINE); @@ -520,7 +520,7 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_FN_F); key(KEY_FN_S); key(KEY_FN_B); - //key(KEY_FN_RIGHT_SHIFT); + // key(KEY_FN_RIGHT_SHIFT); key(KEY_BRL_DOT1); key(KEY_BRL_DOT2); key(KEY_BRL_DOT3); @@ -563,7 +563,7 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_ATTENDANT_TOGGLE); key(KEY_LIGHTS_TOGGLE); key(KEY_ALS_TOGGLE); - //key(KEY_ROTATE_LOCK_TOGGLE); + key(KEY_ROTATE_LOCK_TOGGLE); key(KEY_BUTTONCONFIG); key(KEY_TASKMANAGER); key(KEY_JOURNAL); @@ -571,13 +571,13 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_APPSELECT); key(KEY_SCREENSAVER); key(KEY_VOICECOMMAND); - //key(KEY_ASSISTANT); - //key(KEY_KBD_LAYOUT_NEXT); - //key(KEY_EMOJI_PICKER); - //key(KEY_DICTATE); - //key(KEY_CAMERA_ACCESS_ENABLE); - //key(KEY_CAMERA_ACCESS_DISABLE); - //key(KEY_CAMERA_ACCESS_TOGGLE); + key(KEY_ASSISTANT); + key(KEY_KBD_LAYOUT_NEXT); + // key(KEY_EMOJI_PICKER); + // key(KEY_DICTATE); + // key(KEY_CAMERA_ACCESS_ENABLE); + // key(KEY_CAMERA_ACCESS_DISABLE); + // key(KEY_CAMERA_ACCESS_TOGGLE); key(KEY_BRIGHTNESS_MIN); key(KEY_BRIGHTNESS_MAX); key(KEY_KBDINPUTASSIST_PREV); @@ -604,65 +604,65 @@ bool process_EV_KEY(const QStringList& args){ key(KEY_FASTREVERSE); key(KEY_SLOWREVERSE); key(KEY_DATA); - //key(KEY_ONSCREEN_KEYBOARD); - //key(KEY_PRIVACY_SCREEN_TOGGLE); - //key(KEY_SELECTIVE_SCREENSHOT); - //key(KEY_NEXT_ELEMENT); - //key(KEY_PREVIOUS_ELEMENT); - //key(KEY_AUTOPILOT_ENGAGE_TOGGLE); - //key(KEY_MARK_WAYPOINT); - //key(KEY_SOS); - //key(KEY_NAV_CHART); - //key(KEY_FISHING_CHART); - //key(KEY_SINGLE_RANGE_RADAR); - //key(KEY_DUAL_RANGE_RADAR); - //key(KEY_RADAR_OVERLAY); - //key(KEY_TRADITIONAL_SONAR); - //key(KEY_CLEARVU_SONAR); - //key(KEY_SIDEVU_SONAR); - //key(KEY_NAV_INFO); - //key(KEY_BRIGHTNESS_MENU); - //key(KEY_MACRO1); - //key(KEY_MACRO2); - //key(KEY_MACRO3); - //key(KEY_MACRO4); - //key(KEY_MACRO5); - //key(KEY_MACRO6); - //key(KEY_MACRO7); - //key(KEY_MACRO8); - //key(KEY_MACRO9); - //key(KEY_MACRO10); - //key(KEY_MACRO11); - //key(KEY_MACRO12); - //key(KEY_MACRO13); - //key(KEY_MACRO14); - //key(KEY_MACRO15); - //key(KEY_MACRO16); - //key(KEY_MACRO17); - //key(KEY_MACRO18); - //key(KEY_MACRO19); - //key(KEY_MACRO20); - //key(KEY_MACRO21); - //key(KEY_MACRO22); - //key(KEY_MACRO23); - //key(KEY_MACRO24); - //key(KEY_MACRO25); - //key(KEY_MACRO26); - //key(KEY_MACRO27); - //key(KEY_MACRO28); - //key(KEY_MACRO29); - //key(KEY_MACRO30); - //key(KEY_MACRO_RECORD_START); - //key(KEY_MACRO_RECORD_STOP); - //key(KEY_MACRO_PRESET_CYCLE); - //key(KEY_MACRO_PRESET1); - //key(KEY_MACRO_PRESET2); - //key(KEY_MACRO_PRESET3); - //key(KEY_KBD_LCD_MENU1); - //key(KEY_KBD_LCD_MENU2); - //key(KEY_KBD_LCD_MENU3); - //key(KEY_KBD_LCD_MENU4); - //key(KEY_KBD_LCD_MENU5); + key(KEY_ONSCREEN_KEYBOARD); + // key(KEY_PRIVACY_SCREEN_TOGGLE); + // key(KEY_SELECTIVE_SCREENSHOT); + // key(KEY_NEXT_ELEMENT); + // key(KEY_PREVIOUS_ELEMENT); + // key(KEY_AUTOPILOT_ENGAGE_TOGGLE); + // key(KEY_MARK_WAYPOINT); + // key(KEY_SOS); + // key(KEY_NAV_CHART); + // key(KEY_FISHING_CHART); + // key(KEY_SINGLE_RANGE_RADAR); + // key(KEY_DUAL_RANGE_RADAR); + // key(KEY_RADAR_OVERLAY); + // key(KEY_TRADITIONAL_SONAR); + // key(KEY_CLEARVU_SONAR); + // key(KEY_SIDEVU_SONAR); + // key(KEY_NAV_INFO); + // key(KEY_BRIGHTNESS_MENU); + // key(KEY_MACRO1); + // key(KEY_MACRO2); + // key(KEY_MACRO3); + // key(KEY_MACRO4); + // key(KEY_MACRO5); + // key(KEY_MACRO6); + // key(KEY_MACRO7); + // key(KEY_MACRO8); + // key(KEY_MACRO9); + // key(KEY_MACRO10); + // key(KEY_MACRO11); + // key(KEY_MACRO12); + // key(KEY_MACRO13); + // key(KEY_MACRO14); + // key(KEY_MACRO15); + // key(KEY_MACRO16); + // key(KEY_MACRO17); + // key(KEY_MACRO18); + // key(KEY_MACRO19); + // key(KEY_MACRO20); + // key(KEY_MACRO21); + // key(KEY_MACRO22); + // key(KEY_MACRO23); + // key(KEY_MACRO24); + // key(KEY_MACRO25); + // key(KEY_MACRO26); + // key(KEY_MACRO27); + // key(KEY_MACRO28); + // key(KEY_MACRO29); + // key(KEY_MACRO30); + // key(KEY_MACRO_RECORD_START); + // key(KEY_MACRO_RECORD_STOP); + // key(KEY_MACRO_PRESET_CYCLE); + // key(KEY_MACRO_PRESET1); + // key(KEY_MACRO_PRESET2); + // key(KEY_MACRO_PRESET3); + // key(KEY_KBD_LCD_MENU1); + // key(KEY_KBD_LCD_MENU2); + // key(KEY_KBD_LCD_MENU3); + // key(KEY_KBD_LCD_MENU4); + // key(KEY_KBD_LCD_MENU5); key(KEY_MIN_INTERESTING); key(KEY_MAX); key(KEY_CNT); @@ -731,7 +731,7 @@ bool process_EV_KEY(const QStringList& args){ key(BTN_TOOL_MOUSE); key(BTN_TOOL_LENS); key(BTN_TOOL_QUINTTAP); - //key(BTN_STYLUS3); + key(BTN_STYLUS3); key(BTN_TOUCH); key(BTN_STYLUS); key(BTN_STYLUS2); diff --git a/applications/system-service/application.cpp b/applications/system-service/application.cpp index 2426ad883..6da36e8f3 100644 --- a/applications/system-service/application.cpp +++ b/applications/system-service/application.cpp @@ -284,7 +284,7 @@ void Application::uninterruptApplication(){ case Background: case Backgroundable: if(stateNoSecurityCheck() == Paused){ - touchHandler->clear_buffer(); + systemAPI->clearDeviceBuffers(); kill(-m_process->processId(), SIGCONT); } qDebug() << "Waiting for SIGUSR1 ack"; @@ -303,7 +303,7 @@ void Application::uninterruptApplication(){ break; case Foreground: default: - touchHandler->clear_buffer(); + systemAPI->clearDeviceBuffers(); kill(-m_process->processId(), SIGCONT); startSpan("foreground", "Application is in the foreground"); } @@ -339,7 +339,7 @@ void Application::stopNoSecurityCheck(){ Application* pausedApplication = nullptr; if(state == Paused){ Oxide::Sentry::sentry_span(t, "resume", "Resume paused application", [this, &pausedApplication](){ - touchHandler->clear_buffer(); + systemAPI->clearDeviceBuffers(); auto currentApplication = appsAPI->currentApplicationNoSecurityCheck(); if(currentApplication.path() != path()){ pausedApplication = appsAPI->getApplication(currentApplication); diff --git a/applications/system-service/buttonhandler.cpp b/applications/system-service/buttonhandler.cpp index ff5f7eb7d..d076c023c 100644 --- a/applications/system-service/buttonhandler.cpp +++ b/applications/system-service/buttonhandler.cpp @@ -69,9 +69,11 @@ void ButtonHandler::clear_buffer(){ #ifdef DEBUG qDebug() << "Clearing event buffer on" << buttons.device.c_str(); #endif - ::write(buttons.fd, flood, 512 * 8 * 4 * sizeof(input_event)); + ::write(buttons.fd, flood, EVENT_FLOOD_SIZE); } +input_event* ButtonHandler::event_flood(){ return flood; } + void ButtonHandler::run(){ char name[256]; memset(name, 0, sizeof(name)); diff --git a/applications/system-service/buttonhandler.h b/applications/system-service/buttonhandler.h index 0365c96fc..8ae1b0545 100644 --- a/applications/system-service/buttonhandler.h +++ b/applications/system-service/buttonhandler.h @@ -29,6 +29,7 @@ using namespace std; using namespace Oxide; #define buttonHandler ButtonHandler::init() +#define EVENT_FLOOD_SIZE 512 * 8 * 4 * sizeof(input_event) struct PressRecord { bool pressed = false; @@ -51,6 +52,7 @@ class ButtonHandler : public QThread { ButtonHandler(); void setEnabled(bool enabled); void clear_buffer(); + input_event* event_flood(); public slots: void pressKey(Qt::Key); diff --git a/applications/system-service/keyboarddevice.cpp b/applications/system-service/keyboarddevice.cpp new file mode 100644 index 000000000..729eda738 --- /dev/null +++ b/applications/system-service/keyboarddevice.cpp @@ -0,0 +1,71 @@ +#include "keyboarddevice.h" +#include "buttonhandler.h" +#include "keyboardhandler.h" + +KeyboardDevice::KeyboardDevice(QThread* handler, event_device device) +: QObject(handler), + device(device), + sys("/sys/class/input/" + devName() + "/device/") +{ + moveToThread(handler); + _name = sys.strProperty("name").c_str(); + device.lock(); + notifier = new QSocketNotifier(device.fd, QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, &KeyboardDevice::readEvents); + notifier->setEnabled(true); +} + +KeyboardDevice::~KeyboardDevice(){ + if(exists() && device.locked){ + device.unlock(); + } +} + +QString KeyboardDevice::devName(){ return QFileInfo(device.device.c_str()).baseName(); } + +QString KeyboardDevice::name(){ return _name; } + +QString KeyboardDevice::path(){ return device.device.c_str(); } + +QString KeyboardDevice::id(){ + return QString("%1:%2") + .arg(sys.strProperty("id/vendor").c_str()) + .arg(sys.strProperty("id/product").c_str()); +} + +bool KeyboardDevice::exists(){ return QFile::exists(path()); } + +void KeyboardDevice::flood(){ + if(device.fd == -1 || !device.locked){ + return; + } + ::write(device.fd, buttonHandler->event_flood(), EVENT_FLOOD_SIZE); +} + +void KeyboardDevice::readEvents(){ + notifier->setEnabled(false); + input_event event; + while(::read(device.fd, &event, sizeof(input_event)) > 0){ + switch(event.type){ + case EV_KEY: + pressed[event.code] = event.value; + break; + case EV_SYN: + switch(event.code){ + case SYN_DROPPED: + pressed.clear(); + break; + case SYN_REPORT: + auto handler = static_cast(parent()); + for(auto code : pressed.keys()){ + handler->writeEvent(EV_KEY, code, pressed[code]); + } + handler->writeEvent(EV_SYN, SYN_REPORT, 0); + pressed.clear(); + break; + } + break; + } + } + notifier->setEnabled(true); +} diff --git a/applications/system-service/keyboarddevice.h b/applications/system-service/keyboarddevice.h new file mode 100644 index 000000000..986df9c64 --- /dev/null +++ b/applications/system-service/keyboarddevice.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +using namespace Oxide; + +class KeyboardDevice : public QObject{ + Q_OBJECT + +public: + KeyboardDevice(QThread* handler, event_device device); + ~KeyboardDevice(); + QString devName(); + QString name(); + QString path(); + QString id(); + bool exists(); + void flood(); + +public slots: + void readEvents(); + +private: + event_device device; + SysObject sys; + QString _name; + QSocketNotifier* notifier; + QMap pressed; +}; diff --git a/applications/system-service/keyboardhandler.cpp b/applications/system-service/keyboardhandler.cpp new file mode 100644 index 000000000..9a5bfa947 --- /dev/null +++ b/applications/system-service/keyboardhandler.cpp @@ -0,0 +1,681 @@ +#include "keyboardhandler.h" +#include "eventlistener.h" +#include "buttonhandler.h" + +#include +#include +#include + +KeyboardHandler* KeyboardHandler::init(){ + static KeyboardHandler* instance; + if(instance != nullptr){ + return instance; + } + instance = new KeyboardHandler(); + instance->start(); + return instance; +} + +KeyboardHandler::KeyboardHandler(){ + setObjectName("OxideVirtKeyboard"); + fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if(fd == -1){ + O_WARNING("Failed to open uinput!"); + }else{ + ioctl(fd, UI_SET_EVBIT, EV_REP); + ioctl(fd, UI_SET_EVBIT, EV_LED); + ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_SYN); + + ioctl(fd, UI_SET_KEYBIT, KEY_RESERVED); + ioctl(fd, UI_SET_KEYBIT, KEY_ESC); + ioctl(fd, UI_SET_KEYBIT, KEY_1); + ioctl(fd, UI_SET_KEYBIT, KEY_2); + ioctl(fd, UI_SET_KEYBIT, KEY_3); + ioctl(fd, UI_SET_KEYBIT, KEY_4); + ioctl(fd, UI_SET_KEYBIT, KEY_5); + ioctl(fd, UI_SET_KEYBIT, KEY_6); + ioctl(fd, UI_SET_KEYBIT, KEY_7); + ioctl(fd, UI_SET_KEYBIT, KEY_8); + ioctl(fd, UI_SET_KEYBIT, KEY_9); + ioctl(fd, UI_SET_KEYBIT, KEY_0); + ioctl(fd, UI_SET_KEYBIT, KEY_MINUS); + ioctl(fd, UI_SET_KEYBIT, KEY_EQUAL); + ioctl(fd, UI_SET_KEYBIT, KEY_BACKSPACE); + ioctl(fd, UI_SET_KEYBIT, KEY_TAB); + ioctl(fd, UI_SET_KEYBIT, KEY_Q); + ioctl(fd, UI_SET_KEYBIT, KEY_W); + ioctl(fd, UI_SET_KEYBIT, KEY_E); + ioctl(fd, UI_SET_KEYBIT, KEY_R); + ioctl(fd, UI_SET_KEYBIT, KEY_T); + ioctl(fd, UI_SET_KEYBIT, KEY_Y); + ioctl(fd, UI_SET_KEYBIT, KEY_U); + ioctl(fd, UI_SET_KEYBIT, KEY_I); + ioctl(fd, UI_SET_KEYBIT, KEY_O); + ioctl(fd, UI_SET_KEYBIT, KEY_P); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFTBRACE); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHTBRACE); + ioctl(fd, UI_SET_KEYBIT, KEY_ENTER); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFTCTRL); + ioctl(fd, UI_SET_KEYBIT, KEY_A); + ioctl(fd, UI_SET_KEYBIT, KEY_S); + ioctl(fd, UI_SET_KEYBIT, KEY_D); + ioctl(fd, UI_SET_KEYBIT, KEY_F); + ioctl(fd, UI_SET_KEYBIT, KEY_G); + ioctl(fd, UI_SET_KEYBIT, KEY_H); + ioctl(fd, UI_SET_KEYBIT, KEY_J); + ioctl(fd, UI_SET_KEYBIT, KEY_K); + ioctl(fd, UI_SET_KEYBIT, KEY_L); + ioctl(fd, UI_SET_KEYBIT, KEY_SEMICOLON); + ioctl(fd, UI_SET_KEYBIT, KEY_APOSTROPHE); + ioctl(fd, UI_SET_KEYBIT, KEY_GRAVE); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFTSHIFT); + ioctl(fd, UI_SET_KEYBIT, KEY_BACKSLASH); + ioctl(fd, UI_SET_KEYBIT, KEY_Z); + ioctl(fd, UI_SET_KEYBIT, KEY_X); + ioctl(fd, UI_SET_KEYBIT, KEY_C); + ioctl(fd, UI_SET_KEYBIT, KEY_V); + ioctl(fd, UI_SET_KEYBIT, KEY_B); + ioctl(fd, UI_SET_KEYBIT, KEY_N); + ioctl(fd, UI_SET_KEYBIT, KEY_M); + ioctl(fd, UI_SET_KEYBIT, KEY_COMMA); + ioctl(fd, UI_SET_KEYBIT, KEY_DOT); + ioctl(fd, UI_SET_KEYBIT, KEY_SLASH); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHTSHIFT); + ioctl(fd, UI_SET_KEYBIT, KEY_KPASTERISK); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFTALT); + ioctl(fd, UI_SET_KEYBIT, KEY_SPACE); + ioctl(fd, UI_SET_KEYBIT, KEY_CAPSLOCK); + ioctl(fd, UI_SET_KEYBIT, KEY_F1); + ioctl(fd, UI_SET_KEYBIT, KEY_F2); + ioctl(fd, UI_SET_KEYBIT, KEY_F3); + ioctl(fd, UI_SET_KEYBIT, KEY_F4); + ioctl(fd, UI_SET_KEYBIT, KEY_F5); + ioctl(fd, UI_SET_KEYBIT, KEY_F6); + ioctl(fd, UI_SET_KEYBIT, KEY_F7); + ioctl(fd, UI_SET_KEYBIT, KEY_F8); + ioctl(fd, UI_SET_KEYBIT, KEY_F9); + ioctl(fd, UI_SET_KEYBIT, KEY_F10); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMLOCK); + ioctl(fd, UI_SET_KEYBIT, KEY_SCROLLLOCK); + ioctl(fd, UI_SET_KEYBIT, KEY_KP7); + ioctl(fd, UI_SET_KEYBIT, KEY_KP8); + ioctl(fd, UI_SET_KEYBIT, KEY_KP9); + ioctl(fd, UI_SET_KEYBIT, KEY_KPMINUS); + ioctl(fd, UI_SET_KEYBIT, KEY_KP4); + ioctl(fd, UI_SET_KEYBIT, KEY_KP5); + ioctl(fd, UI_SET_KEYBIT, KEY_KP6); + ioctl(fd, UI_SET_KEYBIT, KEY_KPPLUS); + ioctl(fd, UI_SET_KEYBIT, KEY_KP1); + ioctl(fd, UI_SET_KEYBIT, KEY_KP2); + ioctl(fd, UI_SET_KEYBIT, KEY_KP3); + ioctl(fd, UI_SET_KEYBIT, KEY_KP0); + ioctl(fd, UI_SET_KEYBIT, KEY_KPDOT); + ioctl(fd, UI_SET_KEYBIT, KEY_ZENKAKUHANKAKU); + ioctl(fd, UI_SET_KEYBIT, KEY_102ND); + ioctl(fd, UI_SET_KEYBIT, KEY_F11); + ioctl(fd, UI_SET_KEYBIT, KEY_F12); + ioctl(fd, UI_SET_KEYBIT, KEY_RO); + ioctl(fd, UI_SET_KEYBIT, KEY_KATAKANA); + ioctl(fd, UI_SET_KEYBIT, KEY_HIRAGANA); + ioctl(fd, UI_SET_KEYBIT, KEY_HENKAN); + ioctl(fd, UI_SET_KEYBIT, KEY_KATAKANAHIRAGANA); + ioctl(fd, UI_SET_KEYBIT, KEY_MUHENKAN); + ioctl(fd, UI_SET_KEYBIT, KEY_KPJPCOMMA); + ioctl(fd, UI_SET_KEYBIT, KEY_KPENTER); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHTCTRL); + ioctl(fd, UI_SET_KEYBIT, KEY_KPSLASH); + ioctl(fd, UI_SET_KEYBIT, KEY_SYSRQ); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHTALT); + ioctl(fd, UI_SET_KEYBIT, KEY_LINEFEED); + ioctl(fd, UI_SET_KEYBIT, KEY_HOME); + ioctl(fd, UI_SET_KEYBIT, KEY_UP); + ioctl(fd, UI_SET_KEYBIT, KEY_PAGEUP); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFT); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHT); + ioctl(fd, UI_SET_KEYBIT, KEY_END); + ioctl(fd, UI_SET_KEYBIT, KEY_DOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_PAGEDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_INSERT); + ioctl(fd, UI_SET_KEYBIT, KEY_DELETE); + ioctl(fd, UI_SET_KEYBIT, KEY_MACRO); + ioctl(fd, UI_SET_KEYBIT, KEY_MUTE); + ioctl(fd, UI_SET_KEYBIT, KEY_VOLUMEDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_VOLUMEUP); + ioctl(fd, UI_SET_KEYBIT, KEY_POWER); + ioctl(fd, UI_SET_KEYBIT, KEY_KPEQUAL); + ioctl(fd, UI_SET_KEYBIT, KEY_KPPLUSMINUS); + ioctl(fd, UI_SET_KEYBIT, KEY_PAUSE); + ioctl(fd, UI_SET_KEYBIT, KEY_SCALE); + ioctl(fd, UI_SET_KEYBIT, KEY_KPCOMMA); + ioctl(fd, UI_SET_KEYBIT, KEY_HANGEUL); + ioctl(fd, UI_SET_KEYBIT, KEY_HANGUEL); + ioctl(fd, UI_SET_KEYBIT, KEY_HANJA); + ioctl(fd, UI_SET_KEYBIT, KEY_YEN); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFTMETA); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHTMETA); + ioctl(fd, UI_SET_KEYBIT, KEY_COMPOSE); + ioctl(fd, UI_SET_KEYBIT, KEY_STOP); + ioctl(fd, UI_SET_KEYBIT, KEY_AGAIN); + ioctl(fd, UI_SET_KEYBIT, KEY_PROPS); + ioctl(fd, UI_SET_KEYBIT, KEY_UNDO); + ioctl(fd, UI_SET_KEYBIT, KEY_FRONT); + ioctl(fd, UI_SET_KEYBIT, KEY_COPY); + ioctl(fd, UI_SET_KEYBIT, KEY_OPEN); + ioctl(fd, UI_SET_KEYBIT, KEY_PASTE); + ioctl(fd, UI_SET_KEYBIT, KEY_FIND); + ioctl(fd, UI_SET_KEYBIT, KEY_CUT); + ioctl(fd, UI_SET_KEYBIT, KEY_HELP); + ioctl(fd, UI_SET_KEYBIT, KEY_MENU); + ioctl(fd, UI_SET_KEYBIT, KEY_CALC); + ioctl(fd, UI_SET_KEYBIT, KEY_SETUP); + ioctl(fd, UI_SET_KEYBIT, KEY_SLEEP); + ioctl(fd, UI_SET_KEYBIT, KEY_WAKEUP); + ioctl(fd, UI_SET_KEYBIT, KEY_FILE); + ioctl(fd, UI_SET_KEYBIT, KEY_SENDFILE); + ioctl(fd, UI_SET_KEYBIT, KEY_DELETEFILE); + ioctl(fd, UI_SET_KEYBIT, KEY_XFER); + ioctl(fd, UI_SET_KEYBIT, KEY_PROG1); + ioctl(fd, UI_SET_KEYBIT, KEY_PROG2); + ioctl(fd, UI_SET_KEYBIT, KEY_WWW); + ioctl(fd, UI_SET_KEYBIT, KEY_MSDOS); + ioctl(fd, UI_SET_KEYBIT, KEY_COFFEE); + ioctl(fd, UI_SET_KEYBIT, KEY_SCREENLOCK); + ioctl(fd, UI_SET_KEYBIT, KEY_ROTATE_DISPLAY); + ioctl(fd, UI_SET_KEYBIT, KEY_DIRECTION); + ioctl(fd, UI_SET_KEYBIT, KEY_CYCLEWINDOWS); + ioctl(fd, UI_SET_KEYBIT, KEY_MAIL); + ioctl(fd, UI_SET_KEYBIT, KEY_BOOKMARKS); + ioctl(fd, UI_SET_KEYBIT, KEY_COMPUTER); + ioctl(fd, UI_SET_KEYBIT, KEY_BACK); + ioctl(fd, UI_SET_KEYBIT, KEY_FORWARD); + ioctl(fd, UI_SET_KEYBIT, KEY_CLOSECD); + ioctl(fd, UI_SET_KEYBIT, KEY_EJECTCD); + ioctl(fd, UI_SET_KEYBIT, KEY_EJECTCLOSECD); + ioctl(fd, UI_SET_KEYBIT, KEY_NEXTSONG); + ioctl(fd, UI_SET_KEYBIT, KEY_PLAYPAUSE); + ioctl(fd, UI_SET_KEYBIT, KEY_PREVIOUSSONG); + ioctl(fd, UI_SET_KEYBIT, KEY_STOPCD); + ioctl(fd, UI_SET_KEYBIT, KEY_RECORD); + ioctl(fd, UI_SET_KEYBIT, KEY_REWIND); + ioctl(fd, UI_SET_KEYBIT, KEY_PHONE); + ioctl(fd, UI_SET_KEYBIT, KEY_ISO); + ioctl(fd, UI_SET_KEYBIT, KEY_CONFIG); + ioctl(fd, UI_SET_KEYBIT, KEY_HOMEPAGE); + ioctl(fd, UI_SET_KEYBIT, KEY_REFRESH); + ioctl(fd, UI_SET_KEYBIT, KEY_EXIT); + ioctl(fd, UI_SET_KEYBIT, KEY_MOVE); + ioctl(fd, UI_SET_KEYBIT, KEY_EDIT); + ioctl(fd, UI_SET_KEYBIT, KEY_SCROLLUP); + ioctl(fd, UI_SET_KEYBIT, KEY_SCROLLDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_KPLEFTPAREN); + ioctl(fd, UI_SET_KEYBIT, KEY_KPRIGHTPAREN); + ioctl(fd, UI_SET_KEYBIT, KEY_NEW); + ioctl(fd, UI_SET_KEYBIT, KEY_REDO); + ioctl(fd, UI_SET_KEYBIT, KEY_F13); + ioctl(fd, UI_SET_KEYBIT, KEY_F14); + ioctl(fd, UI_SET_KEYBIT, KEY_F15); + ioctl(fd, UI_SET_KEYBIT, KEY_F16); + ioctl(fd, UI_SET_KEYBIT, KEY_F17); + ioctl(fd, UI_SET_KEYBIT, KEY_F18); + ioctl(fd, UI_SET_KEYBIT, KEY_F19); + ioctl(fd, UI_SET_KEYBIT, KEY_F20); + ioctl(fd, UI_SET_KEYBIT, KEY_F21); + ioctl(fd, UI_SET_KEYBIT, KEY_F22); + ioctl(fd, UI_SET_KEYBIT, KEY_F23); + ioctl(fd, UI_SET_KEYBIT, KEY_F24); + ioctl(fd, UI_SET_KEYBIT, KEY_PLAYCD); + ioctl(fd, UI_SET_KEYBIT, KEY_PAUSECD); + ioctl(fd, UI_SET_KEYBIT, KEY_PROG3); + ioctl(fd, UI_SET_KEYBIT, KEY_PROG4); + ioctl(fd, UI_SET_KEYBIT, KEY_DASHBOARD); + ioctl(fd, UI_SET_KEYBIT, KEY_SUSPEND); + ioctl(fd, UI_SET_KEYBIT, KEY_CLOSE); + ioctl(fd, UI_SET_KEYBIT, KEY_PLAY); + ioctl(fd, UI_SET_KEYBIT, KEY_FASTFORWARD); + ioctl(fd, UI_SET_KEYBIT, KEY_BASSBOOST); + ioctl(fd, UI_SET_KEYBIT, KEY_PRINT); + ioctl(fd, UI_SET_KEYBIT, KEY_HP); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA); + ioctl(fd, UI_SET_KEYBIT, KEY_SOUND); + ioctl(fd, UI_SET_KEYBIT, KEY_QUESTION); + ioctl(fd, UI_SET_KEYBIT, KEY_EMAIL); + ioctl(fd, UI_SET_KEYBIT, KEY_CHAT); + ioctl(fd, UI_SET_KEYBIT, KEY_SEARCH); + ioctl(fd, UI_SET_KEYBIT, KEY_CONNECT); + ioctl(fd, UI_SET_KEYBIT, KEY_FINANCE); + ioctl(fd, UI_SET_KEYBIT, KEY_SPORT); + ioctl(fd, UI_SET_KEYBIT, KEY_SHOP); + ioctl(fd, UI_SET_KEYBIT, KEY_ALTERASE); + ioctl(fd, UI_SET_KEYBIT, KEY_CANCEL); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESSDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESSUP); + ioctl(fd, UI_SET_KEYBIT, KEY_MEDIA); + ioctl(fd, UI_SET_KEYBIT, KEY_SWITCHVIDEOMODE); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDILLUMTOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDILLUMDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDILLUMUP); + ioctl(fd, UI_SET_KEYBIT, KEY_SEND); + ioctl(fd, UI_SET_KEYBIT, KEY_REPLY); + ioctl(fd, UI_SET_KEYBIT, KEY_FORWARDMAIL); + ioctl(fd, UI_SET_KEYBIT, KEY_SAVE); + ioctl(fd, UI_SET_KEYBIT, KEY_DOCUMENTS); + ioctl(fd, UI_SET_KEYBIT, KEY_BATTERY); + ioctl(fd, UI_SET_KEYBIT, KEY_BLUETOOTH); + ioctl(fd, UI_SET_KEYBIT, KEY_WLAN); + ioctl(fd, UI_SET_KEYBIT, KEY_UWB); + ioctl(fd, UI_SET_KEYBIT, KEY_UNKNOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_VIDEO_NEXT); + ioctl(fd, UI_SET_KEYBIT, KEY_VIDEO_PREV); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_CYCLE); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_AUTO); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_ZERO); + ioctl(fd, UI_SET_KEYBIT, KEY_DISPLAY_OFF); + ioctl(fd, UI_SET_KEYBIT, KEY_WWAN); + ioctl(fd, UI_SET_KEYBIT, KEY_WIMAX); + ioctl(fd, UI_SET_KEYBIT, KEY_RFKILL); + ioctl(fd, UI_SET_KEYBIT, KEY_MICMUTE); + ioctl(fd, UI_SET_KEYBIT, BTN_MISC); + ioctl(fd, UI_SET_KEYBIT, BTN_0); + ioctl(fd, UI_SET_KEYBIT, BTN_1); + ioctl(fd, UI_SET_KEYBIT, BTN_2); + ioctl(fd, UI_SET_KEYBIT, BTN_3); + ioctl(fd, UI_SET_KEYBIT, BTN_4); + ioctl(fd, UI_SET_KEYBIT, BTN_5); + ioctl(fd, UI_SET_KEYBIT, BTN_6); + ioctl(fd, UI_SET_KEYBIT, BTN_7); + ioctl(fd, UI_SET_KEYBIT, BTN_8); + ioctl(fd, UI_SET_KEYBIT, BTN_9); + ioctl(fd, UI_SET_KEYBIT, BTN_MOUSE); + ioctl(fd, UI_SET_KEYBIT, BTN_LEFT); + ioctl(fd, UI_SET_KEYBIT, BTN_RIGHT); + ioctl(fd, UI_SET_KEYBIT, BTN_MIDDLE); + ioctl(fd, UI_SET_KEYBIT, BTN_SIDE); + ioctl(fd, UI_SET_KEYBIT, BTN_EXTRA); + ioctl(fd, UI_SET_KEYBIT, BTN_FORWARD); + ioctl(fd, UI_SET_KEYBIT, BTN_BACK); + ioctl(fd, UI_SET_KEYBIT, BTN_TASK); + ioctl(fd, UI_SET_KEYBIT, BTN_JOYSTICK); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER); + ioctl(fd, UI_SET_KEYBIT, BTN_THUMB); + ioctl(fd, UI_SET_KEYBIT, BTN_THUMB2); + ioctl(fd, UI_SET_KEYBIT, BTN_TOP); + ioctl(fd, UI_SET_KEYBIT, BTN_TOP2); + ioctl(fd, UI_SET_KEYBIT, BTN_PINKIE); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE2); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE3); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE4); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE5); + ioctl(fd, UI_SET_KEYBIT, BTN_BASE6); + ioctl(fd, UI_SET_KEYBIT, BTN_DEAD); + ioctl(fd, UI_SET_KEYBIT, BTN_GAMEPAD); + ioctl(fd, UI_SET_KEYBIT, BTN_SOUTH); + ioctl(fd, UI_SET_KEYBIT, BTN_A); + ioctl(fd, UI_SET_KEYBIT, BTN_EAST); + ioctl(fd, UI_SET_KEYBIT, BTN_B); + ioctl(fd, UI_SET_KEYBIT, BTN_C); + ioctl(fd, UI_SET_KEYBIT, BTN_NORTH); + ioctl(fd, UI_SET_KEYBIT, BTN_X); + ioctl(fd, UI_SET_KEYBIT, BTN_WEST); + ioctl(fd, UI_SET_KEYBIT, BTN_Y); + ioctl(fd, UI_SET_KEYBIT, BTN_Z); + ioctl(fd, UI_SET_KEYBIT, BTN_TL); + ioctl(fd, UI_SET_KEYBIT, BTN_TR); + ioctl(fd, UI_SET_KEYBIT, BTN_TL2); + ioctl(fd, UI_SET_KEYBIT, BTN_TR2); + ioctl(fd, UI_SET_KEYBIT, BTN_SELECT); + ioctl(fd, UI_SET_KEYBIT, BTN_START); + ioctl(fd, UI_SET_KEYBIT, BTN_MODE); + ioctl(fd, UI_SET_KEYBIT, BTN_THUMBL); + ioctl(fd, UI_SET_KEYBIT, BTN_THUMBR); + ioctl(fd, UI_SET_KEYBIT, BTN_DIGI); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PEN); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_RUBBER); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_BRUSH); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_PENCIL); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_AIRBRUSH); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_FINGER); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_MOUSE); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_LENS); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_QUINTTAP); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS3); + ioctl(fd, UI_SET_KEYBIT, BTN_TOUCH); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS); + ioctl(fd, UI_SET_KEYBIT, BTN_STYLUS2); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_DOUBLETAP); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_TRIPLETAP); + ioctl(fd, UI_SET_KEYBIT, BTN_TOOL_QUADTAP); + ioctl(fd, UI_SET_KEYBIT, BTN_WHEEL); + ioctl(fd, UI_SET_KEYBIT, BTN_GEAR_DOWN); + ioctl(fd, UI_SET_KEYBIT, BTN_GEAR_UP); + ioctl(fd, UI_SET_KEYBIT, KEY_OK); + ioctl(fd, UI_SET_KEYBIT, KEY_SELECT); + ioctl(fd, UI_SET_KEYBIT, KEY_GOTO); + ioctl(fd, UI_SET_KEYBIT, KEY_CLEAR); + ioctl(fd, UI_SET_KEYBIT, KEY_POWER2); + ioctl(fd, UI_SET_KEYBIT, KEY_OPTION); + ioctl(fd, UI_SET_KEYBIT, KEY_INFO); + ioctl(fd, UI_SET_KEYBIT, KEY_TIME); + ioctl(fd, UI_SET_KEYBIT, KEY_VENDOR); + ioctl(fd, UI_SET_KEYBIT, KEY_ARCHIVE); + ioctl(fd, UI_SET_KEYBIT, KEY_PROGRAM); + ioctl(fd, UI_SET_KEYBIT, KEY_CHANNEL); + ioctl(fd, UI_SET_KEYBIT, KEY_FAVORITES); + ioctl(fd, UI_SET_KEYBIT, KEY_EPG); + ioctl(fd, UI_SET_KEYBIT, KEY_PVR); + ioctl(fd, UI_SET_KEYBIT, KEY_MHP); + ioctl(fd, UI_SET_KEYBIT, KEY_LANGUAGE); + ioctl(fd, UI_SET_KEYBIT, KEY_TITLE); + ioctl(fd, UI_SET_KEYBIT, KEY_SUBTITLE); + ioctl(fd, UI_SET_KEYBIT, KEY_ANGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_FULL_SCREEN); + ioctl(fd, UI_SET_KEYBIT, KEY_ZOOM); + ioctl(fd, UI_SET_KEYBIT, KEY_MODE); + ioctl(fd, UI_SET_KEYBIT, KEY_KEYBOARD); + ioctl(fd, UI_SET_KEYBIT, KEY_ASPECT_RATIO); + ioctl(fd, UI_SET_KEYBIT, KEY_SCREEN); + ioctl(fd, UI_SET_KEYBIT, KEY_PC); + ioctl(fd, UI_SET_KEYBIT, KEY_TV); + ioctl(fd, UI_SET_KEYBIT, KEY_TV2); + ioctl(fd, UI_SET_KEYBIT, KEY_VCR); + ioctl(fd, UI_SET_KEYBIT, KEY_VCR2); + ioctl(fd, UI_SET_KEYBIT, KEY_SAT); + ioctl(fd, UI_SET_KEYBIT, KEY_SAT2); + ioctl(fd, UI_SET_KEYBIT, KEY_CD); + ioctl(fd, UI_SET_KEYBIT, KEY_TAPE); + ioctl(fd, UI_SET_KEYBIT, KEY_RADIO); + ioctl(fd, UI_SET_KEYBIT, KEY_TUNER); + ioctl(fd, UI_SET_KEYBIT, KEY_PLAYER); + ioctl(fd, UI_SET_KEYBIT, KEY_TEXT); + ioctl(fd, UI_SET_KEYBIT, KEY_DVD); + ioctl(fd, UI_SET_KEYBIT, KEY_AUX); + ioctl(fd, UI_SET_KEYBIT, KEY_MP3); + ioctl(fd, UI_SET_KEYBIT, KEY_AUDIO); + ioctl(fd, UI_SET_KEYBIT, KEY_VIDEO); + ioctl(fd, UI_SET_KEYBIT, KEY_DIRECTORY); + ioctl(fd, UI_SET_KEYBIT, KEY_LIST); + ioctl(fd, UI_SET_KEYBIT, KEY_MEMO); + ioctl(fd, UI_SET_KEYBIT, KEY_CALENDAR); + ioctl(fd, UI_SET_KEYBIT, KEY_RED); + ioctl(fd, UI_SET_KEYBIT, KEY_GREEN); + ioctl(fd, UI_SET_KEYBIT, KEY_YELLOW); + ioctl(fd, UI_SET_KEYBIT, KEY_BLUE); + ioctl(fd, UI_SET_KEYBIT, KEY_CHANNELUP); + ioctl(fd, UI_SET_KEYBIT, KEY_CHANNELDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_FIRST); + ioctl(fd, UI_SET_KEYBIT, KEY_LAST); + ioctl(fd, UI_SET_KEYBIT, KEY_AB); + ioctl(fd, UI_SET_KEYBIT, KEY_NEXT); + ioctl(fd, UI_SET_KEYBIT, KEY_RESTART); + ioctl(fd, UI_SET_KEYBIT, KEY_SLOW); + ioctl(fd, UI_SET_KEYBIT, KEY_SHUFFLE); + ioctl(fd, UI_SET_KEYBIT, KEY_BREAK); + ioctl(fd, UI_SET_KEYBIT, KEY_PREVIOUS); + ioctl(fd, UI_SET_KEYBIT, KEY_DIGITS); + ioctl(fd, UI_SET_KEYBIT, KEY_TEEN); + ioctl(fd, UI_SET_KEYBIT, KEY_TWEN); + ioctl(fd, UI_SET_KEYBIT, KEY_VIDEOPHONE); + ioctl(fd, UI_SET_KEYBIT, KEY_GAMES); + ioctl(fd, UI_SET_KEYBIT, KEY_ZOOMIN); + ioctl(fd, UI_SET_KEYBIT, KEY_ZOOMOUT); + ioctl(fd, UI_SET_KEYBIT, KEY_ZOOMRESET); + ioctl(fd, UI_SET_KEYBIT, KEY_WORDPROCESSOR); + ioctl(fd, UI_SET_KEYBIT, KEY_EDITOR); + ioctl(fd, UI_SET_KEYBIT, KEY_SPREADSHEET); + ioctl(fd, UI_SET_KEYBIT, KEY_GRAPHICSEDITOR); + ioctl(fd, UI_SET_KEYBIT, KEY_PRESENTATION); + ioctl(fd, UI_SET_KEYBIT, KEY_DATABASE); + ioctl(fd, UI_SET_KEYBIT, KEY_NEWS); + ioctl(fd, UI_SET_KEYBIT, KEY_VOICEMAIL); + ioctl(fd, UI_SET_KEYBIT, KEY_ADDRESSBOOK); + ioctl(fd, UI_SET_KEYBIT, KEY_MESSENGER); + ioctl(fd, UI_SET_KEYBIT, KEY_DISPLAYTOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_SPELLCHECK); + ioctl(fd, UI_SET_KEYBIT, KEY_LOGOFF); + ioctl(fd, UI_SET_KEYBIT, KEY_DOLLAR); + ioctl(fd, UI_SET_KEYBIT, KEY_EURO); + ioctl(fd, UI_SET_KEYBIT, KEY_FRAMEBACK); + ioctl(fd, UI_SET_KEYBIT, KEY_FRAMEFORWARD); + ioctl(fd, UI_SET_KEYBIT, KEY_CONTEXT_MENU); + ioctl(fd, UI_SET_KEYBIT, KEY_MEDIA_REPEAT); + ioctl(fd, UI_SET_KEYBIT, KEY_10CHANNELSUP); + ioctl(fd, UI_SET_KEYBIT, KEY_10CHANNELSDOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_IMAGES); + ioctl(fd, UI_SET_KEYBIT, KEY_DEL_EOL); + ioctl(fd, UI_SET_KEYBIT, KEY_DEL_EOS); + ioctl(fd, UI_SET_KEYBIT, KEY_INS_LINE); + ioctl(fd, UI_SET_KEYBIT, KEY_DEL_LINE); + ioctl(fd, UI_SET_KEYBIT, KEY_FN); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_ESC); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F1); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F2); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F3); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F4); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F5); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F6); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F7); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F8); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F9); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F10); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F11); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F12); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_1); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_2); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_D); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_E); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_F); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_S); + ioctl(fd, UI_SET_KEYBIT, KEY_FN_B); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT1); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT2); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT3); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT4); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT5); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT6); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT7); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT8); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT9); + ioctl(fd, UI_SET_KEYBIT, KEY_BRL_DOT10); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_0); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_1); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_2); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_3); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_4); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_5); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_6); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_7); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_8); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_9); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_STAR); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_POUND); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_A); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_B); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_C); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_D); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_FOCUS); + ioctl(fd, UI_SET_KEYBIT, KEY_WPS_BUTTON); + ioctl(fd, UI_SET_KEYBIT, KEY_TOUCHPAD_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_TOUCHPAD_ON); + ioctl(fd, UI_SET_KEYBIT, KEY_TOUCHPAD_OFF); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_ZOOMIN); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_ZOOMOUT); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_UP); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_DOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_LEFT); + ioctl(fd, UI_SET_KEYBIT, KEY_CAMERA_RIGHT); + ioctl(fd, UI_SET_KEYBIT, KEY_ATTENDANT_ON); + ioctl(fd, UI_SET_KEYBIT, KEY_ATTENDANT_OFF); + ioctl(fd, UI_SET_KEYBIT, KEY_ATTENDANT_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_LIGHTS_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_UP); + ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_DOWN); + ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_LEFT); + ioctl(fd, UI_SET_KEYBIT, BTN_DPAD_RIGHT); + ioctl(fd, UI_SET_KEYBIT, KEY_ALS_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_ROTATE_LOCK_TOGGLE); + ioctl(fd, UI_SET_KEYBIT, KEY_BUTTONCONFIG); + ioctl(fd, UI_SET_KEYBIT, KEY_TASKMANAGER); + ioctl(fd, UI_SET_KEYBIT, KEY_JOURNAL); + ioctl(fd, UI_SET_KEYBIT, KEY_CONTROLPANEL); + ioctl(fd, UI_SET_KEYBIT, KEY_APPSELECT); + ioctl(fd, UI_SET_KEYBIT, KEY_SCREENSAVER); + ioctl(fd, UI_SET_KEYBIT, KEY_VOICECOMMAND); + ioctl(fd, UI_SET_KEYBIT, KEY_ASSISTANT); + ioctl(fd, UI_SET_KEYBIT, KEY_KBD_LAYOUT_NEXT); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_MIN); + ioctl(fd, UI_SET_KEYBIT, KEY_BRIGHTNESS_MAX); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_PREV); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_NEXT); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_PREVGROUP); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_NEXTGROUP); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_ACCEPT); + ioctl(fd, UI_SET_KEYBIT, KEY_KBDINPUTASSIST_CANCEL); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHT_UP); + ioctl(fd, UI_SET_KEYBIT, KEY_RIGHT_DOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFT_UP); + ioctl(fd, UI_SET_KEYBIT, KEY_LEFT_DOWN); + ioctl(fd, UI_SET_KEYBIT, KEY_ROOT_MENU); + ioctl(fd, UI_SET_KEYBIT, KEY_MEDIA_TOP_MENU); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_11); + ioctl(fd, UI_SET_KEYBIT, KEY_NUMERIC_12); + ioctl(fd, UI_SET_KEYBIT, KEY_AUDIO_DESC); + ioctl(fd, UI_SET_KEYBIT, KEY_3D_MODE); + ioctl(fd, UI_SET_KEYBIT, KEY_NEXT_FAVORITE); + ioctl(fd, UI_SET_KEYBIT, KEY_STOP_RECORD); + ioctl(fd, UI_SET_KEYBIT, KEY_PAUSE_RECORD); + ioctl(fd, UI_SET_KEYBIT, KEY_VOD); + ioctl(fd, UI_SET_KEYBIT, KEY_UNMUTE); + ioctl(fd, UI_SET_KEYBIT, KEY_FASTREVERSE); + ioctl(fd, UI_SET_KEYBIT, KEY_SLOWREVERSE); + ioctl(fd, UI_SET_KEYBIT, KEY_DATA); + ioctl(fd, UI_SET_KEYBIT, KEY_ONSCREEN_KEYBOARD); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY1); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY2); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY3); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY4); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY5); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY6); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY7); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY8); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY9); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY10); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY11); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY12); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY13); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY14); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY15); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY16); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY17); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY18); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY19); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY20); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY21); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY22); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY23); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY24); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY25); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY26); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY27); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY28); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY29); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY30); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY31); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY32); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY33); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY34); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY35); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY36); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY37); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY38); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY39); + ioctl(fd, UI_SET_KEYBIT, BTN_TRIGGER_HAPPY40); + for(int i = LED_NUML; i <= LED_MISC; i++){ + if(ioctl(fd, UI_SET_LEDBIT, i)){ + perror("ioctl set_ledbit"); + exit(-1); + } + } + ioctl(fd, UI_SET_KEYBIT, KEY_ZOOM); + memset(&usetup, 0, sizeof(usetup)); + usetup.id.bustype = BUS_USB; + usetup.id.vendor = 0x0000; + usetup.id.product = 0xFFFF; + strcpy(usetup.name, "Oxide Virtual Keyboard"); + + ioctl(fd, UI_DEV_SETUP, &usetup); + ioctl(fd, UI_DEV_CREATE); + } + reloadDevices(); + deviceSettings.onKeyboardAttachedChanged([this]{ reloadDevices(); }); +} + +KeyboardHandler::~KeyboardHandler(){ + if(fd != -1){ + ioctl(fd, UI_DEV_DESTROY); + close(fd); + } +} + +void KeyboardHandler::flood(){ + qDebug() << "Flooding"; + for(int i = 0; i < 512 * 8; i+=4){ + writeEvent(EV_KEY, KEY_ROTATE_LOCK_TOGGLE, 1); + writeEvent(EV_SYN, SYN_REPORT, 0); + writeEvent(EV_KEY, KEY_ROTATE_LOCK_TOGGLE, 0); + writeEvent(EV_SYN, SYN_REPORT, 0); + } +} + +void KeyboardHandler::writeEvent(int type, int code, int val){ + input_event ie; + ie.type = type; + ie.code = code; + ie.value = val; + // timestamp values below are ignored + ie.time.tv_sec = 0; + ie.time.tv_usec = 0; + ::write(fd, &ie, sizeof(input_event)); +} + +void KeyboardHandler::keyEvent(int code, int value){ + writeEvent(EV_KEY, code, value); + writeEvent(EV_SYN, SYN_REPORT, 0); +} + +bool KeyboardHandler::hasDevice(event_device device){ + for(auto keyboard : devices){ + if(device.device.c_str() == keyboard->path()){ + return true; + } + } + return false; +} + +void KeyboardHandler::reloadDevices(){ + O_DEBUG("Reloading keyboards"); + for(auto device : deviceSettings.keyboards()){ + if(device.device == deviceSettings.getButtonsDevicePath()){ + continue; + } + if(!hasDevice(device) && device.fd != -1){ + auto keyboard = new KeyboardDevice(this, device); + keyboard->moveToThread(this); + O_DEBUG(keyboard->name() << "added"); + devices.append(keyboard); + keyboard->readEvents(); + } + } + QMutableListIterator i(devices); + while(i.hasNext()){ + KeyboardDevice* device = i.next(); + if(device->exists()){ + continue; + } + O_DEBUG(device->name() << "removed"); + i.remove(); + delete device; + } +} diff --git a/applications/system-service/keyboardhandler.h b/applications/system-service/keyboardhandler.h new file mode 100644 index 000000000..e103100d8 --- /dev/null +++ b/applications/system-service/keyboardhandler.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +#include "keyboarddevice.h" + +using namespace Oxide; + +#define keyboardHandler KeyboardHandler::init() + +class KeyboardHandler : public QThread{ + Q_OBJECT + +public: + static KeyboardHandler* init(); + KeyboardHandler(); + ~KeyboardHandler(); + void flood(); + void writeEvent(int type, int code, int val); + +private slots: + void keyEvent(int code, int value); + +private: + int fd; + uinput_setup usetup; + + QList devices; + bool hasDevice(event_device device); + void reloadDevices(); +}; diff --git a/applications/system-service/system-service.pro b/applications/system-service/system-service.pro index 0b2547e50..f68e1f552 100644 --- a/applications/system-service/system-service.pro +++ b/applications/system-service/system-service.pro @@ -21,6 +21,8 @@ SOURCES += \ digitizerhandler.cpp \ eventlistener.cpp \ fifohandler.cpp \ + keyboarddevice.cpp \ + keyboardhandler.cpp \ network.cpp \ notification.cpp \ notificationapi.cpp \ @@ -73,6 +75,8 @@ HEADERS += \ digitizerhandler.h \ eventlistener.h \ fifohandler.h \ + keyboarddevice.h \ + keyboardhandler.h \ network.h \ notification.h \ notificationapi.h \ diff --git a/applications/system-service/systemapi.cpp b/applications/system-service/systemapi.cpp index 28413cf7a..92b5f3ae5 100644 --- a/applications/system-service/systemapi.cpp +++ b/applications/system-service/systemapi.cpp @@ -5,6 +5,7 @@ #include "powerapi.h" #include "wifiapi.h" #include "notificationapi.h" +#include "keyboardhandler.h" QDebug operator<<(QDebug debug, const Touch& touch){ QDebugStateSaver saver(debug); @@ -59,10 +60,8 @@ void SystemAPI::PrepareForSleep(bool suspending){ } releaseSleepInhibitors(); }); - Oxide::Sentry::sentry_span(t, "clear-input", "Clear input buffers", []{ - touchHandler->clear_buffer(); - wacomHandler->clear_buffer(); - buttonHandler->clear_buffer(); + Oxide::Sentry::sentry_span(t, "clear-input", "Clear input buffers", [this]{ + clearDeviceBuffers(); }); qDebug() << "Suspending..."; }); @@ -277,6 +276,7 @@ SystemAPI::SystemAPI(QObject* parent) deviceSettings.onKeyboardAttachedChanged([this]{ emit landscapeChanged(landscape()); }); + keyboardHandler; }); qDebug() << "System API ready to use"; }); @@ -385,6 +385,14 @@ void SystemAPI::lock(){ mutex.lock(); } void SystemAPI::unlock() { mutex.unlock(); } +void SystemAPI::clearDeviceBuffers(){ + touchHandler->clear_buffer(); + wacomHandler->clear_buffer(); + buttonHandler->clear_buffer(); + clearKeyboardBuffers(); +} +void SystemAPI::clearKeyboardBuffers(){ keyboardHandler->flood(); } + void SystemAPI::setSwipeEnabled(int direction, bool enabled){ if(!hasPermission("system")){ return; @@ -897,14 +905,22 @@ void SystemAPI::touchUp(QList touches){ cancelSwipe(touch); return; } - emit bottomAction(); + if(landscape()){ + emit rightAction(); + }else{ + emit bottomAction(); + } }else if(swipeDirection == Down){ if(!swipeStates[Down] || touch->y > location.y() || startLocation.y() - touch->y < swipeLengths[Down]){ // Must end swiping down and having gone far enough cancelSwipe(touch); return; } - emit topAction(); + if(landscape()){ + emit leftAction(); + }else{ + emit topAction(); + } }else if(swipeDirection == Right || swipeDirection == Left){ auto isRM2 = deviceSettings.getDeviceType() == Oxide::DeviceSettings::RM2; auto invalidLeft = !swipeStates[Left] || touch->x < location.x() || touch->x - startLocation.x() < swipeLengths[Left]; @@ -919,9 +935,17 @@ void SystemAPI::touchUp(QList touches){ return; } if(swipeDirection == Left){ - emit rightAction(); + if(landscape()){ + emit topAction(); + }else{ + emit rightAction(); + } }else{ - emit leftAction(); + if(landscape()){ + emit bottomAction(); + }else{ + emit leftAction(); + } } } swipeDirection = None; diff --git a/applications/system-service/systemapi.h b/applications/system-service/systemapi.h index 431f30c89..3436c17e8 100644 --- a/applications/system-service/systemapi.h +++ b/applications/system-service/systemapi.h @@ -87,6 +87,8 @@ class SystemAPI : public APIBase { void startLockTimer(); void lock(); void unlock(); + void clearDeviceBuffers(); + void clearKeyboardBuffers(); Q_INVOKABLE void setSwipeEnabled(int direction, bool enabled); void setSwipeEnabled(SwipeDirection direction, bool enabled); Q_INVOKABLE bool getSwipeEnabled(int direction); @@ -97,6 +99,7 @@ class SystemAPI : public APIBase { void setSwipeLength(SwipeDirection direction, int length); Q_INVOKABLE int getSwipeLength(int direction); int getSwipeLength(SwipeDirection direction); + public slots: void suspend(); void powerOff(); @@ -107,6 +110,7 @@ public slots: void inhibitPowerOff(QDBusMessage message); void uninhibitPowerOff(QDBusMessage message); void toggleSwipes(); + signals: void leftAction(); void homeAction(); diff --git a/applications/xdg-settings/main.cpp b/applications/xdg-settings/main.cpp index 7755558f6..49815894c 100644 --- a/applications/xdg-settings/main.cpp +++ b/applications/xdg-settings/main.cpp @@ -125,7 +125,7 @@ QObject* getObj(QStringList* args, int isGet = false){ return obj; } -int get(QCommandLineParser& parser){ +int get_command(QCommandLineParser& parser){ parser.clearPositionalArguments(); parser.addPositionalArgument("", "", "get"); parser.addPositionalArgument("property", "Property to get", "{property}"); @@ -151,7 +151,7 @@ int get(QCommandLineParser& parser){ return EXIT_SUCCESS; } -int check(QCommandLineParser& parser){ +int check_command(QCommandLineParser& parser){ parser.clearPositionalArguments(); parser.addPositionalArgument("", "", "check"); parser.addPositionalArgument("property", "Property to check", "{property}"); @@ -177,7 +177,7 @@ int check(QCommandLineParser& parser){ return EXIT_SUCCESS; } -int set(QCommandLineParser& parser){ +int set_command(QCommandLineParser& parser){ parser.clearPositionalArguments(); parser.addPositionalArgument("", "", "set"); parser.addPositionalArgument("property", "Property to set", "{property}"); @@ -211,7 +211,7 @@ int set(QCommandLineParser& parser){ return EXIT_FAILURE; } -int list(QCommandLineParser& parser){ +int list_command(QCommandLineParser& parser){ if(!parser.positionalArguments().isEmpty()){ parser.showHelp(EXIT_FAILURE); } @@ -261,7 +261,7 @@ int main(int argc, char *argv[]){ parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsOptions); QStringList args = parser.positionalArguments(); if(parser.isSet(listOption)){ - return list(parser); + return list_command(parser); } if (args.isEmpty()) { parser.showHelp(EXIT_FAILURE); @@ -271,15 +271,15 @@ int main(int argc, char *argv[]){ auto command = args.first(); if(command == "get"){ parser.clearPositionalArguments(); - return get(parser); + return get_command(parser); } if(command == "check"){ parser.clearPositionalArguments(); - return check(parser); + return check_command(parser); } if(command == "set"){ parser.clearPositionalArguments(); - return set(parser); + return set_command(parser); } parser.showHelp(EXIT_FAILURE); } diff --git a/nix/sources.json b/nix/sources.json deleted file mode 100644 index be881ad27..000000000 --- a/nix/sources.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "niv": { - "branch": "master", - "description": "Easy dependency management for Nix projects", - "homepage": "https://github.com/nmattia/niv", - "owner": "nmattia", - "repo": "niv", - "rev": "5830a4dd348d77e39a0f3c4c762ff2663b602d4c", - "sha256": "1d3lsrqvci4qz2hwjrcnd8h5vfkg8aypq3sjd4g3izbc8frwz5sm", - "type": "tarball", - "url": "https://github.com/nmattia/niv/archive/5830a4dd348d77e39a0f3c4c762ff2663b602d4c.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "nix-inclusive": { - "branch": "master", - "description": "Simple inclusive file selection implementation for Nix", - "homepage": "", - "owner": "grahamc", - "repo": "nix-inclusive", - "rev": "6d7062921b2ea3911d2f95a8bd7afdf723d01b9a", - "sha256": "0mx5w1la3yz6m6434dsi25hfra6wm87h854qanm9hsjmxzmgg7w7", - "type": "tarball", - "url": "https://github.com/grahamc/nix-inclusive/archive/6d7062921b2ea3911d2f95a8bd7afdf723d01b9a.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - }, - "nixpkgs": { - "branch": "nixpkgs-unstable", - "description": "Nix Packages collection", - "homepage": "", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "77fda7f672726e1a95c8cd200f27bccfc86c870b", - "sha256": "07qj1d45pkqsmkahbhh7hilwwbvg8vlz1wg497hzjrlx1a57v4y5", - "type": "tarball", - "url": "https://github.com/NixOS/nixpkgs/archive/77fda7f672726e1a95c8cd200f27bccfc86c870b.tar.gz", - "url_template": "https://github.com///archive/.tar.gz" - } -} diff --git a/nix/sources.nix b/nix/sources.nix deleted file mode 100644 index b796fffac..000000000 --- a/nix/sources.nix +++ /dev/null @@ -1,171 +0,0 @@ -# This file has been generated by Niv. - -let - - # - # The fetchers. fetch_ fetches specs of type . - # - - fetch_file = pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchurl { inherit (spec) url sha256; name = name'; } - else - pkgs.fetchurl { inherit (spec) url sha256; name = name'; }; - - fetch_tarball = pkgs: name: spec: - let - name' = sanitizeName name + "-src"; - in - if spec.builtin or true then - builtins_fetchTarball { name = name'; inherit (spec) url sha256; } - else - pkgs.fetchzip { name = name'; inherit (spec) url sha256; }; - - fetch_git = name: spec: - let - ref = - if spec ? ref then spec.ref else - if spec ? branch then "refs/heads/${spec.branch}" else - if spec ? tag then "refs/tags/${spec.tag}" else - abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!"; - in - builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; }; - - fetch_local = spec: spec.path; - - fetch_builtin-tarball = name: throw - ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=tarball -a builtin=true''; - - fetch_builtin-url = name: throw - ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`. - $ niv modify ${name} -a type=file -a builtin=true''; - - # - # Various helpers - # - - # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695 - sanitizeName = name: - ( - concatMapStrings (s: if builtins.isList s then "-" else s) - ( - builtins.split "[^[:alnum:]+._?=-]+" - ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name) - ) - ); - - # The set of packages used when specs are fetched using non-builtins. - mkPkgs = sources: system: - let - sourcesNixpkgs = - import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; }; - hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; - hasThisAsNixpkgsPath = == ./.; - in - if builtins.hasAttr "nixpkgs" sources - then sourcesNixpkgs - else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then - import {} - else - abort - '' - Please specify either (through -I or NIX_PATH=nixpkgs=...) or - add a package called "nixpkgs" to your sources.json. - ''; - - # The actual fetching function. - fetch = pkgs: name: spec: - - if ! builtins.hasAttr "type" spec then - abort "ERROR: niv spec ${name} does not have a 'type' attribute" - else if spec.type == "file" then fetch_file pkgs name spec - else if spec.type == "tarball" then fetch_tarball pkgs name spec - else if spec.type == "git" then fetch_git name spec - else if spec.type == "local" then fetch_local spec - else if spec.type == "builtin-tarball" then fetch_builtin-tarball name - else if spec.type == "builtin-url" then fetch_builtin-url name - else - abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; - - # If the environment variable NIV_OVERRIDE_${name} is set, then use - # the path directly as opposed to the fetched source. - replace = name: drv: - let - saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name; - ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}"; - in - if ersatz == "" then drv else ersatz; - - # Ports of functions for older nix versions - - # a Nix version of mapAttrs if the built-in doesn't exist - mapAttrs = builtins.mapAttrs or ( - f: set: with builtins; - listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) - ); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 - range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 - stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); - - # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 - stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); - concatMapStrings = f: list: concatStrings (map f list); - concatStrings = builtins.concatStringsSep ""; - - # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331 - optionalAttrs = cond: as: if cond then as else {}; - - # fetchTarball version that is compatible between all the versions of Nix - builtins_fetchTarball = { url, name ? null, sha256 }@attrs: - let - inherit (builtins) lessThan nixVersion fetchTarball; - in - if lessThan nixVersion "1.12" then - fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchTarball attrs; - - # fetchurl version that is compatible between all the versions of Nix - builtins_fetchurl = { url, name ? null, sha256 }@attrs: - let - inherit (builtins) lessThan nixVersion fetchurl; - in - if lessThan nixVersion "1.12" then - fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; })) - else - fetchurl attrs; - - # Create the final "sources" from the config - mkSources = config: - mapAttrs ( - name: spec: - if builtins.hasAttr "outPath" spec - then abort - "The values in sources.json should not have an 'outPath' attribute" - else - spec // { outPath = replace name (fetch config.pkgs name spec); } - ) config.sources; - - # The "config" used by the fetchers - mkConfig = - { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null - , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile) - , system ? builtins.currentSystem - , pkgs ? mkPkgs sources system - }: rec { - # The sources, i.e. the attribute set of spec name to spec - inherit sources; - - # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers - inherit pkgs; - }; - -in -mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/shared/liboxide/devicesettings.cpp b/shared/liboxide/devicesettings.cpp new file mode 100644 index 000000000..8ca926f51 --- /dev/null +++ b/shared/liboxide/devicesettings.cpp @@ -0,0 +1,297 @@ +#include "devicesettings.h" + +#include +#include + +#include "debug.h" +#include "liboxide.h" + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) +#define OFF(x) ((x)%BITS_PER_LONG) +#define LONG(x) ((x)/BITS_PER_LONG) +#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) + +using namespace Oxide; + +namespace Oxide { + DeviceSettings& DeviceSettings::instance() { + static DeviceSettings INSTANCE; + return INSTANCE; + } + DeviceSettings::DeviceSettings(): _deviceType(DeviceType::RM1) { + readDeviceType(); + + O_DEBUG("Looking for input devices..."); + QDir dir("/dev/input"); + for(auto path : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::System)){ + if(!wacomPath.empty() && !touchPath.empty() && !buttonsPath.empty()){ + break; + } + O_DEBUG((" Checking " + path + "...").toStdString().c_str()); + QString fullPath(dir.path() + "/" + path); + QFile device(fullPath); + device.open(QIODevice::ReadOnly); + int fd = device.handle(); + int version; + if(ioctl(fd, EVIOCGVERSION, &version)){ + O_DEBUG(" Invalid"); + continue; + } + unsigned long bit[EV_MAX]; + ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); + if(test_bit(EV_KEY, bit)){ + if(checkBitSet(fd, EV_KEY, BTN_STYLUS) && test_bit(EV_ABS, bit)){ + O_DEBUG(" Wacom input device detected"); + if(wacomPath.empty()){ + wacomPath = fullPath.toStdString(); + } + continue; + } + if(checkBitSet(fd, EV_KEY, KEY_POWER)){ + O_DEBUG(" Buttons input device detected"); + if(buttonsPath.empty()){ + buttonsPath = fullPath.toStdString(); + } + continue; + } + } + if(checkBitSet(fd, EV_ABS, ABS_MT_SLOT)){ + O_DEBUG(" Touch input device detected"); + if(touchPath.empty()){ + touchPath = fullPath.toStdString(); + } + continue; + } + O_DEBUG(" Invalid"); + } + if(wacomPath.empty()){ + O_WARNING("Wacom input device not found"); + }else{ + O_DEBUG(("Wacom input device: " + wacomPath).c_str()); + } + if(touchPath.empty()){ + O_WARNING("Touch input device not found"); + }else{ + O_DEBUG(("Touch input device: " + touchPath).c_str()); + } + if(buttonsPath.empty()){ + O_WARNING("Buttons input device not found"); + }else{ + O_DEBUG(("Buttons input device: " + buttonsPath).c_str()); + } + } + DeviceSettings::~DeviceSettings(){} + bool DeviceSettings::checkBitSet(int fd, int type, int i) { + unsigned long bit[NBITS(KEY_MAX)]; + ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit); + return test_bit(i, bit); + } + + void DeviceSettings::readDeviceType() { + QFile file("/sys/devices/soc0/machine"); + if(!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)){ + O_DEBUG("Couldn't open " << file.fileName()); + _deviceType = DeviceType::Unknown; + return; + } + QTextStream in(&file); + QString modelName = in.readLine(); + if (modelName.startsWith("reMarkable 2")) { + O_DEBUG("RM2 detected..."); + _deviceType = DeviceType::RM2; + return; + } + O_DEBUG("RM1 detected..."); + _deviceType = DeviceType::RM1; + } + + DeviceSettings::DeviceType DeviceSettings::getDeviceType() const { return _deviceType; } + + const char* DeviceSettings::getButtonsDevicePath() const { return buttonsPath.c_str(); } + + const char* DeviceSettings::getWacomDevicePath() const { return wacomPath.c_str(); } + + const char* DeviceSettings::getTouchDevicePath() const { return touchPath.c_str(); } + const char* DeviceSettings::getDeviceName() const { + switch(getDeviceType()){ + case DeviceType::RM1: + return "reMarkable 1"; + case DeviceType::RM2: + return "reMarkable 2"; + default: + return "Unknown"; + } + } + + const char* DeviceSettings::getTouchEnvSetting() const { + switch(getDeviceType()) { + case DeviceType::RM1: + return "rotate=180"; + case DeviceType::RM2: + return "rotate=180:invertx"; + default: + return ""; + } + } + + int DeviceSettings::getTouchWidth() const { + switch(getDeviceType()) { + case DeviceType::RM1: + return 767; + case DeviceType::RM2: + return 1403; + default: + return 0; + } + } + int DeviceSettings::getTouchHeight() const { + switch(getDeviceType()) { + case DeviceType::RM1: + return 1023; + case DeviceType::RM2: + return 1871; + default: + return 0; + } + } + const QStringList DeviceSettings::getLocales() { + return execute("localectl", QStringList() << "list-locales" << "--no-pager").split("\n"); + } + QString DeviceSettings::getLocale() { + QFile file("/etc/locale.conf"); + if(file.open(QFile::ReadOnly)){ + while(!file.atEnd()){ + QString line = file.readLine(); + QStringList fields = line.split("="); + if(fields.first().trimmed() != "LANG"){ + continue; + } + return fields.at(1).trimmed(); + } + } + return qEnvironmentVariable("LANG", "C"); + } + void DeviceSettings::setLocale(const QString& locale) { + if(debugEnabled()){ + qDebug() << "Setting locale:" << locale; + } + qputenv("LANG", locale.toUtf8()); + QProcess::execute("localectl", QStringList() << "set-locale" << locale); + } + const QStringList DeviceSettings::getTimezones() { + return execute("timedatectl", QStringList() << "list-timezones" << "--no-pager").split("\n"); + } + QString DeviceSettings::getTimezone() { + auto lines = execute("timedatectl", QStringList() << "show").split("\n"); + for(auto line : lines){ + QStringList fields = line.split("="); + if(fields.first().trimmed() != "Timezone"){ + continue; + } + return fields.at(1).trimmed(); + } + return "UTC"; + } + void DeviceSettings::setTimezone(const QString& timezone) { + if(debugEnabled()){ + qDebug() << "Setting timezone:" << timezone; + } + QProcess::execute("timedatectl", QStringList() << "set-timezone" << timezone); + } + void DeviceSettings::setupQtEnvironment(bool touch){ + auto qt_version = qVersion(); + if (strcmp(qt_version, QT_VERSION_STR) != 0){ + qDebug() << "Version mismatch, Runtime: " << qt_version << ", Build: " << QT_VERSION_STR; + } + #ifdef __arm__ + qputenv("QMLSCENE_DEVICE", "epaper"); + qputenv("QT_QUICK_BACKEND","epaper"); + qputenv("QT_QPA_PLATFORM", "epaper:enable_fonts"); + #endif + if(touch){ + qputenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS", deviceSettings.getTouchEnvSetting()); + qputenv("QT_QPA_GENERIC_PLUGINS", "evdevtablet"); + } + } + bool DeviceSettings::keyboardAttached(){ return !physicalKeyboards().empty(); } + void DeviceSettings::onKeyboardAttachedChanged(std::function callback){ + auto manager = QGuiApplicationPrivate::inputDeviceManager(); + QObject::connect(manager, &QInputDeviceManager::deviceListChanged, [callback](QInputDeviceManager::DeviceType type){ + if(type == QInputDeviceManager::DeviceTypeKeyboard){ + callback(); + } + }); + } + QList DeviceSettings::keyboards(){ + QList keyboards; + QDir dir("/dev/input"); + for(auto path : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::System)){ + QString fullPath(dir.path() + "/" + path); + if( + fullPath == QString::fromStdString(buttonsPath) + || fullPath == QString::fromStdString(wacomPath) + || fullPath == QString::fromStdString(touchPath) + ){ + continue; + } + QFile device(fullPath); + device.open(QIODevice::ReadOnly); + int fd = device.handle(); + int version; + if(ioctl(fd, EVIOCGVERSION, &version)){ + continue; + } + unsigned long bit[EV_MAX]; + ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); + if(!test_bit(EV_KEY, bit)){ + continue; + } + if(checkBitSet(fd, EV_KEY, BTN_STYLUS) && test_bit(EV_ABS, bit)){ + continue; + } + SysObject sys("/sys/class/input/" + path + "/device"); + auto vendor = sys.strProperty("id/vendor"); + if(vendor == "0000"){ + continue; + } + auto product = sys.strProperty("id/product"); + if(product == "0000"){ + continue; + } + keyboards.append(event_device(fullPath.toStdString(), O_RDWR | O_NONBLOCK)); + } + return keyboards; + } + static QStringList VIRTUAL_KEYBOARD_IDS( + QStringList() << "0fac:0ade" << "0fac:1ade" << "0000:ffff" + ); + QList DeviceSettings::physicalKeyboards(){ + QList physicalKeyboards; + for(auto device : keyboards()){ + auto name = QFileInfo(device.device.c_str()).baseName(); + SysObject sys("/sys/class/input/" + name + "/device/id"); + auto id = QString("%1:%2") + .arg(sys.strProperty("vendor").c_str()) + .arg(sys.strProperty("product").c_str()); + if(!VIRTUAL_KEYBOARD_IDS.contains(id)){ + physicalKeyboards.append(device); + } + } + return physicalKeyboards; + } + QList DeviceSettings::virtualKeyboards(){ + QList physicalKeyboards; + for(auto device : keyboards()){ + auto name = QFileInfo(device.device.c_str()).baseName(); + SysObject sys("/sys/class/input/" + name + "/device/id"); + auto id = QString("%1:%2") + .arg(sys.strProperty("vendor").c_str()) + .arg(sys.strProperty("product").c_str()); + if(VIRTUAL_KEYBOARD_IDS.contains(id)){ + physicalKeyboards.append(device); + } + } + return physicalKeyboards; + } +} diff --git a/shared/liboxide/devicesettings.h b/shared/liboxide/devicesettings.h new file mode 100644 index 000000000..8193d7e2d --- /dev/null +++ b/shared/liboxide/devicesettings.h @@ -0,0 +1,150 @@ +/*! + * \addtogroup Oxide + * \brief The DeviceSettings class + * @{ + * \file + */ +#pragma once +#include "liboxide_global.h" +#include "event_device.h" + +/*! + * \def deviceSettings() + * \brief Get the Oxide::DeviceSettings instance + */ +#define deviceSettings Oxide::DeviceSettings::instance() + +namespace Oxide{ + /*! + * \brief Device specific values + */ + class LIBOXIDE_EXPORT DeviceSettings{ + public: + /*! + * \brief Known device types + */ + enum DeviceType { + Unknown, /*!< Unknown device type >*/ + RM1, /*!< reMarkable 1 >*/ + RM2 /*!< reMarkable 2 >*/ + }; + /*! + * \brief Get the static instance of this class. You should use the deviceSettings macro instead. + * \return The static instance + * \sa deviceSettings + */ + static DeviceSettings& instance(); + /*! + * \brief Get the path to the buttons input device + * \return Path to the buttons device + */ + const char* getButtonsDevicePath() const; + /*! + * \brief Get the path to the wacom input device + * \return Path to the wacom device + */ + const char* getWacomDevicePath() const; + /*! + * \brief Get the path to the touch input device + * \return Path to the touch device + */ + const char* getTouchDevicePath() const; + /*! + * \brief Get the Qt environment settings for the device + * \return The Qt environment settings for the device + */ + const char* getTouchEnvSetting() const; + /*! + * \brief Get the device type + * \return The device type + */ + DeviceType getDeviceType() const; + /*! + * \brief Get the human readable device name + * \return Human readable device name + */ + const char* getDeviceName() const; + /*! + * \brief Get the max width for touch input on the device + * \return Max width for touch input + */ + int getTouchWidth() const; + /*! + * \brief Get the max height for touch input on the device + * \return Max height for touch input + */ + int getTouchHeight() const; + /*! + * \brief Get the list of possible locales on the device + * \return The list of possible locales on the device + */ + const QStringList getLocales(); + /*! + * \brief Get the current set locale + * \return The current locale + */ + QString getLocale(); + /*! + * \brief Set the current locale + * \param locale Locale to set + */ + void setLocale(const QString& locale); + /*! + * \brief Get the list of possible timezones on the device + * \return The list of possible timezones on the device + */ + const QStringList getTimezones(); + /*! + * \brief Get the current set timezone + * \return The current timezone + */ + QString getTimezone(); + /*! + * \brief Set the current timezone + * \param locale Timezone to set + */ + void setTimezone(const QString& timezone); + /*! + * \brief Setup the Qt environment + * \snippet examples/oxide.cpp setupQtEnvironment + */ + void setupQtEnvironment(bool touch = true); + /*! + * \brief Check if a keyboard is attached + * \return If a keyboard is attached + */ + bool keyboardAttached(); + /*! + * \brief Run a callback when keyboardAttached changes + * \param callback Callback to run + */ + void onKeyboardAttachedChanged(std::function callback); + /*! + * \brief Get the list of all keyboard evdev devices + * \return All keyboard devices + */ + QList keyboards(); + /*! + * \brief Get the list of all physical keyboard evdev devices + * \return All physical keyboard devices + */ + QList physicalKeyboards(); + /*! + * \brief Get the list of all virtual keyboard evdev devices + * \return All virtual keyboard devices + */ + QList virtualKeyboards(); + + private: + DeviceType _deviceType; + + DeviceSettings(); + ~DeviceSettings(); + void readDeviceType(); + bool checkBitSet(int fd, int type, int i); + std::string buttonsPath = ""; + std::string wacomPath = ""; + std::string touchPath = ""; + }; +} +/*! @} */ diff --git a/shared/liboxide/event_device.cpp b/shared/liboxide/event_device.cpp index 5bdbff2ea..cf004300b 100644 --- a/shared/liboxide/event_device.cpp +++ b/shared/liboxide/event_device.cpp @@ -34,14 +34,16 @@ namespace Oxide { int event_device::lock(){ O_DEBUG("locking " << device.c_str()); - int result = ioctl(fd, EVIOCGRAB, 1); - if(result == EBUSY){ - O_WARNING("Device is busy"); - }else if(result != 0){ - O_WARNING("Unknown error: " << result); - }else{ + if(ioctl(fd, EVIOCGRAB, 1) == 0){ locked = true; O_DEBUG(device.c_str() << " locked"); + return 0; + } + int result = errno; + if(result == EBUSY){ + O_WARNING("Device is already grabbed"); + }else{ + O_WARNING("Unknown error: " << result); } return result; } diff --git a/shared/liboxide/liboxide.cpp b/shared/liboxide/liboxide.cpp index 8e7596330..81cc510c8 100644 --- a/shared/liboxide/liboxide.cpp +++ b/shared/liboxide/liboxide.cpp @@ -5,9 +5,6 @@ #include #include -#include -#include - #include #include #include @@ -15,12 +12,6 @@ #include #include -#define BITS_PER_LONG (sizeof(long) * 8) -#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1) -#define OFF(x) ((x)%BITS_PER_LONG) -#define LONG(x) ((x)/BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1) - namespace Oxide { QString execute(const QString& program, const QStringList& args){ QString output; @@ -130,302 +121,4 @@ namespace Oxide { } return result->gr_gid; } - DeviceSettings& DeviceSettings::instance() { - static DeviceSettings INSTANCE; - return INSTANCE; - } - DeviceSettings::DeviceSettings(): _deviceType(DeviceType::RM1) { - readDeviceType(); - - O_DEBUG("Looking for input devices..."); - QDir dir("/dev/input"); - for(auto path : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::System)){ - O_DEBUG((" Checking " + path + "...").toStdString().c_str()); - QString fullPath(dir.path() + "/" + path); - QFile device(fullPath); - device.open(QIODevice::ReadOnly); - int fd = device.handle(); - int version; - if(ioctl(fd, EVIOCGVERSION, &version)){ - O_DEBUG(" Invalid"); - continue; - } - unsigned long bit[EV_MAX]; - ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); - if(test_bit(EV_KEY, bit)){ - if(checkBitSet(fd, EV_KEY, BTN_STYLUS) && test_bit(EV_ABS, bit)){ - O_DEBUG(" Wacom input device detected"); - if(wacomPath.empty()){ - wacomPath = fullPath.toStdString(); - } - continue; - } - if(checkBitSet(fd, EV_KEY, KEY_POWER)){ - O_DEBUG(" Buttons input device detected"); - if(buttonsPath.empty()){ - buttonsPath = fullPath.toStdString(); - } - continue; - } - } - if(checkBitSet(fd, EV_ABS, ABS_MT_SLOT)){ - O_DEBUG(" Touch input device detected"); - if(touchPath.empty()){ - touchPath = fullPath.toStdString(); - } - continue; - } - O_DEBUG(" Invalid"); - } - if(wacomPath.empty()){ - O_WARNING("Wacom input device not found"); - }else{ - O_DEBUG(("Wacom input device: " + wacomPath).c_str()); - } - if(touchPath.empty()){ - O_WARNING("Touch input device not found"); - }else{ - O_DEBUG(("Touch input device: " + touchPath).c_str()); - } - if(buttonsPath.empty()){ - O_WARNING("Buttons input device not found"); - }else{ - O_DEBUG(("Buttons input device: " + buttonsPath).c_str()); - } - } - DeviceSettings::~DeviceSettings(){} - bool DeviceSettings::checkBitSet(int fd, int type, int i) { - unsigned long bit[NBITS(KEY_MAX)]; - ioctl(fd, EVIOCGBIT(type, KEY_MAX), bit); - return test_bit(i, bit); - } - - void DeviceSettings::readDeviceType() { - QFile file("/sys/devices/soc0/machine"); - if(!file.exists() || !file.open(QIODevice::ReadOnly | QIODevice::Text)){ - O_DEBUG("Couldn't open " << file.fileName()); - _deviceType = DeviceType::Unknown; - return; - } - QTextStream in(&file); - QString modelName = in.readLine(); - if (modelName.startsWith("reMarkable 2")) { - O_DEBUG("RM2 detected..."); - _deviceType = DeviceType::RM2; - return; - } - O_DEBUG("RM1 detected..."); - _deviceType = DeviceType::RM1; - } - - DeviceSettings::DeviceType DeviceSettings::getDeviceType() const { return _deviceType; } - - const char* DeviceSettings::getButtonsDevicePath() const { return buttonsPath.c_str(); } - - const char* DeviceSettings::getWacomDevicePath() const { return wacomPath.c_str(); } - - const char* DeviceSettings::getTouchDevicePath() const { return touchPath.c_str(); } - const char* DeviceSettings::getDeviceName() const { - switch(getDeviceType()){ - case DeviceType::RM1: - return "reMarkable 1"; - case DeviceType::RM2: - return "reMarkable 2"; - default: - return "Unknown"; - } - } - - const char* DeviceSettings::getTouchEnvSetting() const { - switch(getDeviceType()) { - case DeviceType::RM1: - return "rotate=180"; - case DeviceType::RM2: - return "rotate=180:invertx"; - default: - return ""; - } - } - - int DeviceSettings::getTouchWidth() const { - switch(getDeviceType()) { - case DeviceType::RM1: - return 767; - case DeviceType::RM2: - return 1403; - default: - return 0; - } - } - int DeviceSettings::getTouchHeight() const { - switch(getDeviceType()) { - case DeviceType::RM1: - return 1023; - case DeviceType::RM2: - return 1871; - default: - return 0; - } - } - const QStringList DeviceSettings::getLocales() { - return execute("localectl", QStringList() << "list-locales" << "--no-pager").split("\n"); - } - QString DeviceSettings::getLocale() { - QFile file("/etc/locale.conf"); - if(file.open(QFile::ReadOnly)){ - while(!file.atEnd()){ - QString line = file.readLine(); - QStringList fields = line.split("="); - if(fields.first().trimmed() != "LANG"){ - continue; - } - return fields.at(1).trimmed(); - } - } - return qEnvironmentVariable("LANG", "C"); - } - void DeviceSettings::setLocale(const QString& locale) { - if(debugEnabled()){ - qDebug() << "Setting locale:" << locale; - } - qputenv("LANG", locale.toUtf8()); - QProcess::execute("localectl", QStringList() << "set-locale" << locale); - } - const QStringList DeviceSettings::getTimezones() { - return execute("timedatectl", QStringList() << "list-timezones" << "--no-pager").split("\n"); - } - QString DeviceSettings::getTimezone() { - auto lines = execute("timedatectl", QStringList() << "show").split("\n"); - for(auto line : lines){ - QStringList fields = line.split("="); - if(fields.first().trimmed() != "Timezone"){ - continue; - } - return fields.at(1).trimmed(); - } - return "UTC"; - } - void DeviceSettings::setTimezone(const QString& timezone) { - if(debugEnabled()){ - qDebug() << "Setting timezone:" << timezone; - } - QProcess::execute("timedatectl", QStringList() << "set-timezone" << timezone); - } - void DeviceSettings::setupQtEnvironment(bool touch){ - auto qt_version = qVersion(); - if (strcmp(qt_version, QT_VERSION_STR) != 0){ - qDebug() << "Version mismatch, Runtime: " << qt_version << ", Build: " << QT_VERSION_STR; - } -#ifdef __arm__ - qputenv("QMLSCENE_DEVICE", "epaper"); - qputenv("QT_QUICK_BACKEND","epaper"); - qputenv("QT_QPA_PLATFORM", "epaper:enable_fonts"); -#endif - if(touch){ - qputenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS", deviceSettings.getTouchEnvSetting()); - qputenv("QT_QPA_GENERIC_PLUGINS", "evdevtablet"); - } - } - bool DeviceSettings::keyboardAttached(){ - QDir dir("/dev/input"); - for(auto path : dir.entryList(QDir::Files | QDir::NoSymLinks | QDir::System)){ - O_DEBUG((" Checking " + path + "...").toStdString().c_str()); - QString fullPath(dir.path() + "/" + path); - if( - fullPath == QString::fromStdString(buttonsPath) - || fullPath == QString::fromStdString(wacomPath) - || fullPath == QString::fromStdString(touchPath) - ){ - continue; - } - QFile device(fullPath); - device.open(QIODevice::ReadOnly); - int fd = device.handle(); - int version; - if(ioctl(fd, EVIOCGVERSION, &version)){ - continue; - } - unsigned long bit[EV_MAX]; - ioctl(fd, EVIOCGBIT(0, EV_MAX), bit); - if(!test_bit(EV_KEY, bit)){ - continue; - } - if(checkBitSet(fd, EV_KEY, BTN_STYLUS) && test_bit(EV_ABS, bit)){ - continue; - } - SysObject sys("/sys/class/input/" + path + "/device"); - auto vendor = sys.strProperty("id/vendor"); - if(vendor == "0000"){ - continue; - } - auto product = sys.strProperty("id/product"); - if(product == "0000"){ - continue; - } - auto id = vendor+":"+product; - if(id == "0fac:0ade" || id == "0fac:1ade"){ - continue; - } - O_DEBUG("Keyboard found: " << sys.strProperty("name").c_str()); - return true; - } - O_DEBUG("No keyboard found"); - return false; - } - void DeviceSettings::onKeyboardAttachedChanged(std::function callback){ - auto manager = QGuiApplicationPrivate::inputDeviceManager(); - QObject::connect(manager, &QInputDeviceManager::deviceListChanged, [callback](QInputDeviceManager::DeviceType type){ - if(type == QInputDeviceManager::DeviceTypeKeyboard){ - callback(); - } - }); - } - WifiNetworks XochitlSettings::wifinetworks(){ - beginGroup("wifinetworks"); - QMap wifinetworks; - for(const QString& key : allKeys()){ - QVariantMap network = value(key).toMap(); - wifinetworks[key] = network; - } - endGroup(); - return wifinetworks; - } - void XochitlSettings::setWifinetworks(const WifiNetworks& wifinetworks){ - beginGroup("wifinetworks"); - for(const QString& key : wifinetworks.keys()){ - setValue(key, wifinetworks.value(key)); - } - endGroup(); - sync(); - } - QVariantMap XochitlSettings::getWifiNetwork(const QString& name){ - beginGroup("wifinetworks"); - QVariantMap network = value(name).toMap(); - endGroup(); - return network; - } - void XochitlSettings::setWifiNetwork(const QString& name, QVariantMap properties){ - beginGroup("wifinetworks"); - setValue(name, properties); - endGroup(); - sync(); - } - void XochitlSettings::resetWifinetworks(){} - XochitlSettings::~XochitlSettings(){} - SharedSettings::~SharedSettings(){} - O_SETTINGS_PROPERTY_BODY(XochitlSettings, QString, General, passcode) - O_SETTINGS_PROPERTY_BODY(XochitlSettings, bool, General, wifion) - O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, version) - O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, firstLaunch, true) - O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, telemetry, false) - O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, applicationUsage, false) - O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, crashReport, true) - O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, lockOnSuspend, true) - O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, autoSleep, 5) - O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, autoLock, 5) - O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, pin) - O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, onLogin) - O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, onFailedLogin) } - -#include "moc_liboxide.cpp" diff --git a/shared/liboxide/liboxide.h b/shared/liboxide/liboxide.h index ae0ac1e1a..184603f4c 100644 --- a/shared/liboxide/liboxide.h +++ b/shared/liboxide/liboxide.h @@ -18,6 +18,9 @@ #include "slothandler.h" #include "sysobject.h" #include "debug.h" +#include "devicesettings.h" +#include "xochitlsettings.h" +#include "sharedsettings.h" #if defined(LIBOXIDE_LIBRARY) #include "oxide_sentry.h" #else @@ -44,27 +47,7 @@ Q_IMPORT_PLUGIN(QsgEpaperPlugin) #ifndef APP_VERSION #define APP_VERSION VERSION #endif -/*! - * \def deviceSettings() - * \brief Get the Oxide::DeviceSettings instance - */ -#define deviceSettings Oxide::DeviceSettings::instance() -/*! - * \def xochitlSettings() - * \brief Get the Oxide::XochitlSettings instance - */ -#define xochitlSettings Oxide::XochitlSettings::instance() -/*! - * \def sharedSettings() - * \brief Get the Oxide::SharedSettings instance - */ -#define sharedSettings Oxide::SharedSettings::instance() -/*! - * \brief Wifi Network definition - */ -typedef QMap WifiNetworks; -Q_DECLARE_METATYPE(WifiNetworks); /*! * \brief The main Oxide namespace */ @@ -148,395 +131,5 @@ namespace Oxide { * \snippet examples/oxide.cpp getGID */ LIBOXIDE_EXPORT gid_t getGID(const QString& name); - /*! - * \brief Device specific values - */ - class LIBOXIDE_EXPORT DeviceSettings{ - public: - /*! - * \brief Known device types - */ - enum DeviceType { - Unknown, /*!< Unknown device type >*/ - RM1, /*!< reMarkable 1 >*/ - RM2 /*!< reMarkable 2 >*/ - }; - /*! - * \brief Get the static instance of this class. You should use the deviceSettings macro instead. - * \return The static instance - * \sa deviceSettings - */ - static DeviceSettings& instance(); - /*! - * \brief Get the path to the buttons input device - * \return Path to the buttons device - */ - const char* getButtonsDevicePath() const; - /*! - * \brief Get the path to the wacom input device - * \return Path to the wacom device - */ - const char* getWacomDevicePath() const; - /*! - * \brief Get the path to the touch input device - * \return Path to the touch device - */ - const char* getTouchDevicePath() const; - /*! - * \brief Get the Qt environment settings for the device - * \return The Qt environment settings for the device - */ - const char* getTouchEnvSetting() const; - /*! - * \brief Get the device type - * \return The device type - */ - DeviceType getDeviceType() const; - /*! - * \brief Get the human readable device name - * \return Human readable device name - */ - const char* getDeviceName() const; - /*! - * \brief Get the max width for touch input on the device - * \return Max width for touch input - */ - int getTouchWidth() const; - /*! - * \brief Get the max height for touch input on the device - * \return Max height for touch input - */ - int getTouchHeight() const; - /*! - * \brief Get the list of possible locales on the device - * \return The list of possible locales on the device - */ - const QStringList getLocales(); - /*! - * \brief Get the current set locale - * \return The current locale - */ - QString getLocale(); - /*! - * \brief Set the current locale - * \param locale Locale to set - */ - void setLocale(const QString& locale); - /*! - * \brief Get the list of possible timezones on the device - * \return The list of possible timezones on the device - */ - const QStringList getTimezones(); - /*! - * \brief Get the current set timezone - * \return The current timezone - */ - QString getTimezone(); - /*! - * \brief Set the current timezone - * \param locale Timezone to set - */ - void setTimezone(const QString& timezone); - /*! - * \brief Setup the Qt environment - * \snippet examples/oxide.cpp setupQtEnvironment - */ - void setupQtEnvironment(bool touch = true); - /*! - * \brief Check if a keyboard is attached - * \return If a keyboard is attached - */ - bool keyboardAttached(); - /*! - * \brief Run a callback when keyboardAttached changes - * \param callback Callback to run - */ - void onKeyboardAttachedChanged(std::function callback); - - private: - DeviceType _deviceType; - - DeviceSettings(); - ~DeviceSettings(); - void readDeviceType(); - bool checkBitSet(int fd, int type, int i); - std::string buttonsPath = ""; - std::string wacomPath = ""; - std::string touchPath = ""; - }; - /*! - * \brief Manage Xochitl settings - */ - class LIBOXIDE_EXPORT XochitlSettings : public SettingsFile { - Q_OBJECT - /*! - * \fn instance - * \brief Get the static instance of this class. You should use the xochitlSettings macro instead. - * \return The static instance - * \sa xochitlSettings - */ - // cppcheck-suppress uninitMemberVarPrivate - // cppcheck-suppress unusedFunction - O_SETTINGS(XochitlSettings, "/home/root/.config/remarkable/xochitl.conf") - /*! - * \property passcode - * \brief The passcode used to unlock the device - * \sa set_passcode, passcodeChanged - */ - /*! - * \fn set_passcode - * \param _arg_passcode The passcode used to unlock the device - * \brief Set the passcode used to unlock the device - */ - /*! - * \fn passcodeChanged - * \brief The passcode used to unlock the device has changed - */ - O_SETTINGS_PROPERTY(QString, General, passcode) - /*! - * \property wifion - * \brief If wifi is on or off - * \sa set_wifion, wifionChanged - */ - /*! - * \fn set_wifion - * \param _arg_wifion If wifi should be on or off - * \brief Turn wifi on or off - */ - /*! - * \fn wifionChanged - * \brief Wifi has been turned on or off - */ - O_SETTINGS_PROPERTY(bool, General, wifion) - /*! - * \property XochitlSettings::wifinetworks - * \brief List of wifi networks - * \sa setWifinetworks, wifinetworksChanged - */ - Q_PROPERTY(WifiNetworks wifinetworks MEMBER m_wifinetworks READ wifinetworks WRITE setWifinetworks RESET resetWifinetworks NOTIFY wifinetworksChanged) - - public: - WifiNetworks wifinetworks(); - /*! - * \brief Set the list of wifi networks - * \param wifinetworks List of wifi networks to replace with - */ - void setWifinetworks(const WifiNetworks& wifinetworks); - /*! - * \brief Get a specific wifi network - * \param name SSID of the wifi network - * \return The wifi network properties - */ - QVariantMap getWifiNetwork(const QString& name); - /*! - * \brief Set the properties for a specific wifi network - * \param name SSID of the wifi network - * \param properties The wifi network properties - */ - void setWifiNetwork(const QString& name, QVariantMap properties); - void resetWifinetworks(); - - signals: - /*! - * \brief The contents of the wifi network list has changed - */ - void wifinetworksChanged(WifiNetworks); - - private: - ~XochitlSettings(); - WifiNetworks m_wifinetworks; - }; - /*! - * \brief Shared settings for Oxide - */ - class LIBOXIDE_EXPORT SharedSettings : public SettingsFile { - Q_OBJECT - /*! - * \fn instance - * \brief Get the static instance of this class. You should use the sharedSettings macro instead. - * \return The static instance - * \sa sharedSettings - */ - // cppcheck-suppress uninitMemberVarPrivate - O_SETTINGS(SharedSettings, "/home/root/.config/Eeems/shared.conf") - /*! - * \property version - * \brief Current version of the settings file - * \sa set_version, versionChanged - */ - /*! - * \fn versionChanged - * \brief If the version number has changed - */ - O_SETTINGS_PROPERTY(int, General, version) - /*! - * \property firstLaunch - * \brief If this is the first time that things have been run - * \sa set_firstLaunch, firstLaunchChanged - */ - /*! - * \fn set_firstLaunch - * \param _arg_firstLaunch - * \brief Change the state of firstLaunch - */ - /*! - * \fn firstLaunchChanged - * \brief If firstLaunch has changed - */ - O_SETTINGS_PROPERTY(bool, General, firstLaunch, true) - /*! - * \property telemetry - * \brief If telemetry reporting is enabled or not - * \sa set_telemetry, telemetryChanged - */ - /*! - * \fn set_telemetry - * \param _arg_telemetry - * \brief Enable or disable telemetry reporting - */ - /*! - * \fn telemetryChanged - * \brief If telemetry reporting has been enabled or disabled - */ - O_SETTINGS_PROPERTY(bool, General, telemetry, false) - /*! - * \property applicationUsage - * \brief If application usage reporting is enabled or not - * \sa set_applicationUsage, applicationUsageChanged - */ - /*! - * \fn set_applicationUsage - * \param _arg_applicationUsage - * \brief Enable or disable application usage reporting - */ - /*! - * \fn applicationUsageChanged - * \brief If application usage reporting has been enabled or disabled - */ - O_SETTINGS_PROPERTY(bool, General, applicationUsage, false) - /*! - * \property crashReport - * \brief If crash reporting is enabled or not - * \sa set_crashReport, crashReportChanged - */ - /*! - * \fn set_crashReport - * \param _arg_crashReport - * \brief Enable or disable crash reporting - */ - /*! - * \fn crashReportChanged - * \brief If crash reporting has been enabled or disabled - */ - O_SETTINGS_PROPERTY(bool, General, crashReport, true) - /*! - * \property lockOnSuspend - * \brief If the device should lock on suspend or not - * \sa set_lockOnSuspend, lockOnSuspendChanged - */ - /*! - * \fn set_lockOnSuspend - * \param _arg_lockOnSuspend - * \brief Enable or disable locking on suspend - */ - /*! - * \fn lockOnSuspendChanged - * \brief If lock on suspend has been enabled or disabled - */ - O_SETTINGS_PROPERTY(bool, General, lockOnSuspend, true) - /*! - * \property autoSleep - * \brief How long without activity before the device should suspend - * \sa set_autoSleep, autoSleepChanged - */ - /*! - * \fn set_autoSleep - * \param _arg_autoSleep - * \brief Change autoSleep - */ - /*! - * \fn autoSleepChanged - * \brief If autoSleep has been changed - */ - O_SETTINGS_PROPERTY(int, General, autoSleep, 5) - /*! - * \property autoLock - * \brief How long without activity before the device should suspend - * \sa set_autoLock, autoLockChanged - */ - /*! - * \fn set_autoLock - * \param _arg_autoLock - * \brief Change autoLock - */ - /*! - * \fn autoLockChanged - * \brief If autoLock has been changed - */ - O_SETTINGS_PROPERTY(int, General, autoLock, 5) - /*! - * \property pin - * \brief The lockscreen pin - * \sa set_pin, pinChanged - */ - /*! - * \fn set_pin - * \param _arg_pin - * \brief Change lockscreen pin - */ - /*! - * \fn has_pin - * \brief Change lockscreen pin - * \return If the lockscreen pin is set - */ - /*! - * \fn pinChanged - * \brief If the lockscreen pin has been changed - */ - O_SETTINGS_PROPERTY(QString, Lockscreen, pin) - /*! - * \property onLogin - * \brief The lockscreen onLogin - * \sa set_onLogin, onLoginChanged - */ - /*! - * \fn set_onLogin - * \param _arg_onLogin - * \brief Change lockscreen onLogin - */ - /*! - * \fn has_onLogin - * \brief If lockscreen onLogin has been set - * \return If the lockscreen onLogin is set - */ - /*! - * \fn onLoginChanged - * \brief If the lockscreen onLogin has been changed - */ - O_SETTINGS_PROPERTY(QString, Lockscreen, onLogin) - /*! - * \property onFailedLogin - * \brief The lockscreen onFailedLogin - * \sa set_onFailedLogin, onFailedLoginChanged - */ - /*! - * \fn set_onFailedLogin - * \param _arg_onFailedLogin - * \brief Change lockscreen onFailedLogin - */ - /*! - * \fn has_onFailedLogin - * \brief If lockscreen onFailedLogin has been set - * \return If the lockscreen onFailedLogin is set - */ - /*! - * \fn onFailedLoginChanged - * \brief If the lockscreen onFailedLogin has been changed - */ - O_SETTINGS_PROPERTY(QString, Lockscreen, onFailedLogin) - - private: - ~SharedSettings(); - }; } /*! @} */ diff --git a/shared/liboxide/liboxide.pro b/shared/liboxide/liboxide.pro index 0eb1f587c..d0645d2d7 100644 --- a/shared/liboxide/liboxide.pro +++ b/shared/liboxide/liboxide.pro @@ -23,6 +23,7 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs depr SOURCES += \ applications.cpp \ debug.cpp \ + devicesettings.cpp \ event_device.cpp \ eventfilter.cpp \ json.cpp \ @@ -31,14 +32,17 @@ SOURCES += \ oxideqml.cpp \ power.cpp \ settingsfile.cpp \ + sharedsettings.cpp \ slothandler.cpp \ sysobject.cpp \ - signalhandler.cpp + signalhandler.cpp \ + xochitlsettings.cpp HEADERS += \ applications.h \ dbus.h \ debug.h \ + devicesettings.h \ event_device.h \ eventfilter.h \ liboxide_global.h \ @@ -49,9 +53,11 @@ HEADERS += \ power.h \ json.h \ settingsfile.h \ + sharedsettings.h \ slothandler.h \ sysobject.h \ - signalhandler.h + signalhandler.h \ + xochitlsettings.h PRECOMPILED_HEADER = \ liboxide_stable.h diff --git a/shared/liboxide/oxide_sentry.cpp b/shared/liboxide/oxide_sentry.cpp index 8aaaa2abe..5cbf7976a 100644 --- a/shared/liboxide/oxide_sentry.cpp +++ b/shared/liboxide/oxide_sentry.cpp @@ -1,5 +1,5 @@ #include "oxide_sentry.h" -#include "liboxide.h" +#include "sharedsettings.h" #include #include @@ -23,6 +23,8 @@ std::string readFile(const std::string& path){ buffer << t.rdbuf(); return buffer.str(); } + +#include "devicesettings.h" #endif static void* invalid_mem = (void *)1; diff --git a/shared/liboxide/settingsfile.h b/shared/liboxide/settingsfile.h index c32c94d69..5de0183df 100644 --- a/shared/liboxide/settingsfile.h +++ b/shared/liboxide/settingsfile.h @@ -6,6 +6,7 @@ #pragma once #include "liboxide_global.h" +#include "debug.h" #include #include diff --git a/shared/liboxide/sharedsettings.cpp b/shared/liboxide/sharedsettings.cpp new file mode 100644 index 000000000..e98eda536 --- /dev/null +++ b/shared/liboxide/sharedsettings.cpp @@ -0,0 +1,16 @@ +#include "sharedsettings.h" + +namespace Oxide{ + SharedSettings::~SharedSettings(){} + O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, version) + O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, firstLaunch, true) + O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, telemetry, false) + O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, applicationUsage, false) + O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, crashReport, true) + O_SETTINGS_PROPERTY_BODY(SharedSettings, bool, General, lockOnSuspend, true) + O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, autoSleep, 5) + O_SETTINGS_PROPERTY_BODY(SharedSettings, int, General, autoLock, 5) + O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, pin) + O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, onLogin) + O_SETTINGS_PROPERTY_BODY(SharedSettings, QString, Lockscreen, onFailedLogin) +} diff --git a/shared/liboxide/sharedsettings.h b/shared/liboxide/sharedsettings.h new file mode 100644 index 000000000..f1f4d4454 --- /dev/null +++ b/shared/liboxide/sharedsettings.h @@ -0,0 +1,212 @@ +/*! + * \addtogroup Oxide + * \brief The shared settings class + * @{ + * \file + */ +#pragma once +#include "liboxide_global.h" +#include "settingsfile.h" + +/*! + * \def sharedSettings() + * \brief Get the Oxide::SharedSettings instance + */ +#define sharedSettings Oxide::SharedSettings::instance() + +namespace Oxide{ + /*! + * \brief Shared settings for Oxide + */ + class LIBOXIDE_EXPORT SharedSettings : public SettingsFile { + Q_OBJECT + /*! + * \fn instance + * \brief Get the static instance of this class. You should use the sharedSettings macro instead. + * \return The static instance + * \sa sharedSettings + */ + // cppcheck-suppress uninitMemberVarPrivate + O_SETTINGS(SharedSettings, "/home/root/.config/Eeems/shared.conf") + /*! + * \property version + * \brief Current version of the settings file + * \sa set_version, versionChanged + */ + /*! + * \fn versionChanged + * \brief If the version number has changed + */ + O_SETTINGS_PROPERTY(int, General, version) + /*! + * \property firstLaunch + * \brief If this is the first time that things have been run + * \sa set_firstLaunch, firstLaunchChanged + */ + /*! + * \fn set_firstLaunch + * \param _arg_firstLaunch + * \brief Change the state of firstLaunch + */ + /*! + * \fn firstLaunchChanged + * \brief If firstLaunch has changed + */ + O_SETTINGS_PROPERTY(bool, General, firstLaunch, true) + /*! + * \property telemetry + * \brief If telemetry reporting is enabled or not + * \sa set_telemetry, telemetryChanged + */ + /*! + * \fn set_telemetry + * \param _arg_telemetry + * \brief Enable or disable telemetry reporting + */ + /*! + * \fn telemetryChanged + * \brief If telemetry reporting has been enabled or disabled + */ + O_SETTINGS_PROPERTY(bool, General, telemetry, false) + /*! + * \property applicationUsage + * \brief If application usage reporting is enabled or not + * \sa set_applicationUsage, applicationUsageChanged + */ + /*! + * \fn set_applicationUsage + * \param _arg_applicationUsage + * \brief Enable or disable application usage reporting + */ + /*! + * \fn applicationUsageChanged + * \brief If application usage reporting has been enabled or disabled + */ + O_SETTINGS_PROPERTY(bool, General, applicationUsage, false) + /*! + * \property crashReport + * \brief If crash reporting is enabled or not + * \sa set_crashReport, crashReportChanged + */ + /*! + * \fn set_crashReport + * \param _arg_crashReport + * \brief Enable or disable crash reporting + */ + /*! + * \fn crashReportChanged + * \brief If crash reporting has been enabled or disabled + */ + O_SETTINGS_PROPERTY(bool, General, crashReport, true) + /*! + * \property lockOnSuspend + * \brief If the device should lock on suspend or not + * \sa set_lockOnSuspend, lockOnSuspendChanged + */ + /*! + * \fn set_lockOnSuspend + * \param _arg_lockOnSuspend + * \brief Enable or disable locking on suspend + */ + /*! + * \fn lockOnSuspendChanged + * \brief If lock on suspend has been enabled or disabled + */ + O_SETTINGS_PROPERTY(bool, General, lockOnSuspend, true) + /*! + * \property autoSleep + * \brief How long without activity before the device should suspend + * \sa set_autoSleep, autoSleepChanged + */ + /*! + * \fn set_autoSleep + * \param _arg_autoSleep + * \brief Change autoSleep + */ + /*! + * \fn autoSleepChanged + * \brief If autoSleep has been changed + */ + O_SETTINGS_PROPERTY(int, General, autoSleep, 5) + /*! + * \property autoLock + * \brief How long without activity before the device should suspend + * \sa set_autoLock, autoLockChanged + */ + /*! + * \fn set_autoLock + * \param _arg_autoLock + * \brief Change autoLock + */ + /*! + * \fn autoLockChanged + * \brief If autoLock has been changed + */ + O_SETTINGS_PROPERTY(int, General, autoLock, 5) + /*! + * \property pin + * \brief The lockscreen pin + * \sa set_pin, pinChanged + */ + /*! + * \fn set_pin + * \param _arg_pin + * \brief Change lockscreen pin + */ + /*! + * \fn has_pin + * \brief Change lockscreen pin + * \return If the lockscreen pin is set + */ + /*! + * \fn pinChanged + * \brief If the lockscreen pin has been changed + */ + O_SETTINGS_PROPERTY(QString, Lockscreen, pin) + /*! + * \property onLogin + * \brief The lockscreen onLogin + * \sa set_onLogin, onLoginChanged + */ + /*! + * \fn set_onLogin + * \param _arg_onLogin + * \brief Change lockscreen onLogin + */ + /*! + * \fn has_onLogin + * \brief If lockscreen onLogin has been set + * \return If the lockscreen onLogin is set + */ + /*! + * \fn onLoginChanged + * \brief If the lockscreen onLogin has been changed + */ + O_SETTINGS_PROPERTY(QString, Lockscreen, onLogin) + /*! + * \property onFailedLogin + * \brief The lockscreen onFailedLogin + * \sa set_onFailedLogin, onFailedLoginChanged + */ + /*! + * \fn set_onFailedLogin + * \param _arg_onFailedLogin + * \brief Change lockscreen onFailedLogin + */ + /*! + * \fn has_onFailedLogin + * \brief If lockscreen onFailedLogin has been set + * \return If the lockscreen onFailedLogin is set + */ + /*! + * \fn onFailedLoginChanged + * \brief If the lockscreen onFailedLogin has been changed + */ + O_SETTINGS_PROPERTY(QString, Lockscreen, onFailedLogin) + + private: + ~SharedSettings(); + }; +} + +/*! @} */ diff --git a/shared/liboxide/xochitlsettings.cpp b/shared/liboxide/xochitlsettings.cpp new file mode 100644 index 000000000..05b05e388 --- /dev/null +++ b/shared/liboxide/xochitlsettings.cpp @@ -0,0 +1,41 @@ +#include "xochitlsettings.h" + +using namespace Oxide; + +namespace Oxide{ + WifiNetworks XochitlSettings::wifinetworks(){ + beginGroup("wifinetworks"); + QMap wifinetworks; + for(const QString& key : allKeys()){ + QVariantMap network = value(key).toMap(); + wifinetworks[key] = network; + } + endGroup(); + return wifinetworks; + } + void XochitlSettings::setWifinetworks(const WifiNetworks& wifinetworks){ + beginGroup("wifinetworks"); + for(const QString& key : wifinetworks.keys()){ + setValue(key, wifinetworks.value(key)); + } + endGroup(); + sync(); + } + QVariantMap XochitlSettings::getWifiNetwork(const QString& name){ + beginGroup("wifinetworks"); + QVariantMap network = value(name).toMap(); + endGroup(); + return network; + } + void XochitlSettings::setWifiNetwork(const QString& name, QVariantMap properties){ + beginGroup("wifinetworks"); + setValue(name, properties); + endGroup(); + sync(); + } + void XochitlSettings::resetWifinetworks(){} + XochitlSettings::~XochitlSettings(){} + O_SETTINGS_PROPERTY_BODY(XochitlSettings, QString, General, passcode) + O_SETTINGS_PROPERTY_BODY(XochitlSettings, bool, General, wifion) +} +#include "moc_xochitlsettings.cpp" diff --git a/shared/liboxide/xochitlsettings.h b/shared/liboxide/xochitlsettings.h new file mode 100644 index 000000000..0f946b25e --- /dev/null +++ b/shared/liboxide/xochitlsettings.h @@ -0,0 +1,106 @@ +/*! + * \addtogroup Oxide + * \brief The xochitl setttings class + * @{ + * \file + */ +#pragma once +#include "liboxide_global.h" +#include "settingsfile.h" + +/*! + * \def xochitlSettings() + * \brief Get the Oxide::XochitlSettings instance + */ +#define xochitlSettings Oxide::XochitlSettings::instance() +/*! + * \brief Wifi Network definition + */ +typedef QMap WifiNetworks; +Q_DECLARE_METATYPE(WifiNetworks); + +namespace Oxide{ + /*! + * \brief Manage Xochitl settings + */ + class LIBOXIDE_EXPORT XochitlSettings : public SettingsFile { + Q_OBJECT + /*! + * \fn instance + * \brief Get the static instance of this class. You should use the xochitlSettings macro instead. + * \return The static instance + * \sa xochitlSettings + */ + // cppcheck-suppress uninitMemberVarPrivate + // cppcheck-suppress unusedFunction + O_SETTINGS(XochitlSettings, "/home/root/.config/remarkable/xochitl.conf") + /*! + * \property passcode + * \brief The passcode used to unlock the device + * \sa set_passcode, passcodeChanged + */ + /*! + * \fn set_passcode + * \param _arg_passcode The passcode used to unlock the device + * \brief Set the passcode used to unlock the device + */ + /*! + * \fn passcodeChanged + * \brief The passcode used to unlock the device has changed + */ + O_SETTINGS_PROPERTY(QString, General, passcode) + /*! + * \property wifion + * \brief If wifi is on or off + * \sa set_wifion, wifionChanged + */ + /*! + * \fn set_wifion + * \param _arg_wifion If wifi should be on or off + * \brief Turn wifi on or off + */ + /*! + * \fn wifionChanged + * \brief Wifi has been turned on or off + */ + O_SETTINGS_PROPERTY(bool, General, wifion) + /*! + * \property XochitlSettings::wifinetworks + * \brief List of wifi networks + * \sa setWifinetworks, wifinetworksChanged + */ + Q_PROPERTY(WifiNetworks wifinetworks MEMBER m_wifinetworks READ wifinetworks WRITE setWifinetworks RESET resetWifinetworks NOTIFY wifinetworksChanged) + + public: + WifiNetworks wifinetworks(); + /*! + * \brief Set the list of wifi networks + * \param wifinetworks List of wifi networks to replace with + */ + void setWifinetworks(const WifiNetworks& wifinetworks); + /*! + * \brief Get a specific wifi network + * \param name SSID of the wifi network + * \return The wifi network properties + */ + QVariantMap getWifiNetwork(const QString& name); + /*! + * \brief Set the properties for a specific wifi network + * \param name SSID of the wifi network + * \param properties The wifi network properties + */ + void setWifiNetwork(const QString& name, QVariantMap properties); + void resetWifinetworks(); + + signals: + /*! + * \brief The contents of the wifi network list has changed + */ + void wifinetworksChanged(WifiNetworks); + + private: + ~XochitlSettings(); + WifiNetworks m_wifinetworks; + }; +} +/*! @} */