7 Commits

Author SHA1 Message Date
ff8bc15bc5 feat: add default config path (#4)
All checks were successful
CD / build (amd64, usbmakroboard-amd64, linux_amd64) (push) Successful in 1m9s
CD / build (arm64, usbmakroboard-arm64, linux_arm64) (push) Successful in 4m0s
CD / release (push) Successful in 7s
Reviewed-on: #4
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2025-12-27 13:29:53 +01:00
0d0509b8f1 ci(renovate): add renovate (#8)
Reviewed-on: #8
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2025-12-27 13:05:35 +01:00
36e37c46ba ci: unify ci and cd build step (#6)
Reviewed-on: #6
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2025-12-27 13:03:21 +01:00
83f4a683cd ci: add simple test pipeline (#5)
Reviewed-on: #5
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
2025-12-27 12:40:15 +01:00
c839c1ff49 feat: add install target 2024-05-09 11:51:53 +02:00
a13048665f chore: fix type 2024-05-06 20:39:48 +02:00
e522001182 chore: remove files from previous version 2024-05-06 20:39:21 +02:00
9 changed files with 154 additions and 140 deletions

View File

@@ -0,0 +1,49 @@
name: Build
on:
workflow_call:
inputs:
runner:
type: string
default: "linux_amd64"
arch:
type: string
default: "amd64"
jobs:
build:
runs-on:
- ubuntu-latest
- ${{ inputs.runner }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
fetch-depth: 0
- run: |
sudo apt-get update
sudo apt-get install -y build-essential cmake zip
- name: Build
run: |
mkdir -p build
cd build
cmake ..
cmake --build .
- name: Verify binary
run: |
test -f build/usbmakroboard && echo "Binary built successfully" || exit 1
- name: Create zip archive
run: |
cd build
zip usbmakroboard-linux-${{ inputs.arch }}.zip usbmakroboard
- name: Generate checksum
run: |
cd build
sha256sum usbmakroboard-linux-${{ inputs.arch }}.zip > usbmakroboard-linux-${{ inputs.arch }}.zip.sha256
- name: Upload artifacts
uses: ChristopherHX/gitea-upload-artifact@v4
with:
name: usbmakroboard-${{ inputs.arch }}
path: |
build/usbmakroboard-linux-${{ inputs.arch }}.zip
build/usbmakroboard-linux-${{ inputs.arch }}.zip.sha256
retention-days: 1

58
.gitea/workflows/cd.yaml Normal file
View File

@@ -0,0 +1,58 @@
name: CD
on:
push:
branches:
- main
paths:
- "src/**"
- "CMakeLists.txt"
- "schemas/**"
workflow_dispatch:
jobs:
build:
strategy:
matrix:
include:
- runner: linux_amd64
arch: amd64
artifact_name: usbmakroboard-amd64
- runner: linux_arm64
arch: arm64
artifact_name: usbmakroboard-arm64
uses: ./.gitea/workflows/build.yaml
with:
runner: ${{ matrix.runner }}
arch: ${{ matrix.arch }}
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
fetch-depth: 0
- uses: https://gitea.t000-n.de/t.behrendt/conventional-semantic-git-tag-increment@0.1.22
id: tag
with:
token: ${{ secrets.GITEA_TOKEN }}
prerelease: ${{ github.event_name == 'workflow_dispatch' }}
- uses: https://gitea.t000-n.de/t.behrendt/actions/release-git-tag@0.1.0
with:
tag: ${{ steps.tag.outputs.new-tag }}
- uses: ChristopherHX/gitea-download-artifact@v4
with:
path: artifacts
- name: Create release
uses: akkuman/gitea-release-action@v1
with:
tag_name: ${{ steps.tag.outputs.new-tag }}
name: ${{ steps.tag.outputs.new-tag }}
files: |
artifacts/usbmakroboard-amd64/usbmakroboard-linux-amd64.zip
artifacts/usbmakroboard-amd64/usbmakroboard-linux-amd64.zip.sha256
artifacts/usbmakroboard-arm64/usbmakroboard-linux-arm64.zip
artifacts/usbmakroboard-arm64/usbmakroboard-linux-arm64.zip.sha256
prerelease: ${{ github.event_name == 'workflow_dispatch' }}
token: ${{ secrets.GITHUB_TOKEN }}

20
.gitea/workflows/ci.yaml Normal file
View File

@@ -0,0 +1,20 @@
name: CI
on:
pull_request:
jobs:
build:
strategy:
matrix:
include:
- runner: linux_amd64
arch: amd64
artifact_name: usbmakroboard-amd64
- runner: linux_arm64
arch: arm64
artifact_name: usbmakroboard-arm64
uses: ./.gitea/workflows/build.yaml
with:
runner: ${{ matrix.runner }}
arch: ${{ matrix.arch }}

View File

@@ -44,3 +44,5 @@ endif()
# Link spdlog with your executable
target_link_libraries(usbmakroboard PRIVATE spdlog::spdlog)
install(TARGETS usbmakroboard DESTINATION "${CMAKE_INSTALL_PREFIX}/bin")

View File

@@ -1,6 +1,6 @@
# UsbMakroBoard
## Cudos
## Kudos
For info that with "EVIOCGRAB" the keyboard events can be consumed exclusively by one application: https://stackoverflow.com/questions/29942421/read-barcodes-from-input-event-linux-c/29956584#29956584
@@ -12,7 +12,9 @@ For info that with "EVIOCGRAB" the keyboard events can be consumed exclusively b
## Configuration
The configuration can be
The configuration can be provided by either specifying a config file path via the `-c` parameter. If no parameter is provided, the default config path under `$HOME/.config/UsbMakroBoard.yaml` is used.
Find the config schema in [schemas/config.schema.json](./schemas/config.schema.json) as well as a default config in [config.yaml](./config.yaml).
## Allowing non-root access to the device

BIN
main

Binary file not shown.

137
main.c
View File

@@ -1,137 +0,0 @@
// https://stackoverflow.com/questions/20943322/accessing-keys-from-linux-input-device
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
/**
* +--+--+--+--+
* |30|48|46|32|
* +--+--+--+--+
* |18|33|34|35|
* +--+--+--+--+
* |23|36|37|38|
* +--+--+--+--+
* |50|49|24|25|
* +--+--+--+--+
* |16|19|31|20|
* +--+--+--+--+
* */
enum p_key {
p11 = 30,
p12 = 48,
p13 = 46,
p14 = 32,
p21 = 18,
p22 = 33,
p23 = 34,
p24 = 35,
p31 = 23,
p32 = 36,
p33 = 37,
p34 = 38,
p41 = 50,
p42 = 49,
p43 = 24,
p44 = 25,
p51 = 16,
p52 = 19,
p53 = 31,
p54 = 20
};
int main(void)
{
const char* dev = "/dev/input/by-id/usb-MAX_Falcon_20_RGB-if02-event-kbd"; //at.event26
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
// This grabs the device, so the we do not just listen to events but we actually consume them! This way the keypresses are not handled by any other handler!
// https://stackoverflow.com/questions/29942421/read-barcodes-from-input-event-linux-c/29956584#29956584
if (ioctl(fd, EVIOCGRAB, 1)) {
const int saved_errno = errno;
close(fd);
return errno = (saved_errno) ? errno : EACCES;
}
// Main-Loop
while (1) {
n = read(fd, &ev, sizeof ev);
//n = ioctl(fd, EVIOCGRAB, 1);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2) {
//printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
if (evval[ev.value] == "RELEASED") {
switch((int)ev.code) {
case p11:
system("notify-send 'Screenlayout: default'; /home/tbehrendt/.screenlayout/default.sh");
break;
case p12:
system("notify-send 'Screenlayout: main low res'; /home/tbehrendt/.screenlayout/main_low_res.sh");
break;
case p13:
system("notify-send 'Screenlayout: tv mirror'; /home/tbehrendt/.screenlayout/tv_mirror.sh");
break;
case p14:
system("notify-send 'Screenlayout: tv standalone'; /home/tbehrendt/.screenlayout/tv_standalone.sh");
break;
case p21: printf("p21\n"); break;
case p22: printf("p22\n"); break;
case p23: printf("p23\n"); break;
case p24: printf("p24\n"); break;
case p31: printf("p31\n"); break;
case p32: printf("p32\n"); break;
case p33: printf("p33\n"); break;
case p34: printf("p34\n"); break;
case p41: printf("p41\n"); break;
case p42: printf("p42\n"); break;
case p43: printf("p43\n"); break;
case p44: printf("p44\n"); break;
case p51:
system("notify-send mute toggled;pactl set-sink-mute @DEFAULT_SINK@ toggle");
break;
case p52:
system("notify-send 'VOL +5%'; pactl set-sink-volume @DEFAULT_SINK@ +5%");
break;
case p53:
system("notify-send 'VOL -5%'; pactl set-sink-volume @DEFAULT_SINK@ -5%");
break;
case p54:
system("/home/tbehrendt/.scripts/makroboard/p51.sh &");
break;
}
}
}
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}

7
renovate.json Normal file
View File

@@ -0,0 +1,7 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>t.behrendt/renovate-configs:common",
"local>t.behrendt/renovate-configs:action"
]
}

View File

@@ -7,6 +7,7 @@
#include <fcntl.h>
#include <linux/input.h>
#include <iostream>
#include <cstdlib>
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_sinks.h>
#include <yaml-cpp/yaml.h>
@@ -57,7 +58,7 @@ std::pair<int, int> mapKeyEventToRowColumn(int keyEventNumber, const std::unorde
std::string getConfigPathFromCliArguments(int argc, char *argv[])
{
std::string configPath = "config.yaml";
std::string configPath;
int opt;
while ((opt = getopt(argc, argv, "c:")) != -1)
{
@@ -71,6 +72,18 @@ std::string getConfigPathFromCliArguments(int argc, char *argv[])
exit(EXIT_FAILURE);
}
}
if (configPath.empty()) {
const char *home = std::getenv("HOME");
if (home != nullptr) {
configPath = std::string(home) + "/.config/usbMakroBoard.yaml";
}
else {
std::cerr << "HOME environment variable is not set. Exiting.\n";
exit(EXIT_FAILURE);
}
}
return configPath;
}