Где-то неделю назад я прочитал статью: Индикация раскладки клавиатуры подсветкой — решение для GNOME. И что-то так вдохновился, что решил сделать что-то подобное для себя, у меня KDE. Начал делать, воспроизвёл подсветку одним цветом достаточно быстро, а потом решил, может, улучшить и рисовать прямо флаг страны относительно языка раскладки? И кажется получилось неплохо и весело.
https://github.com/jidckii/kolor-keyboard

⚠️ AI Дисклеймер
Этот проект почти полностью сгенерирован с помощью AI Claude Code.
Использование на свой страх и риск. Автор проекта не несёт ответственности за любые последствия, включая возможные проблемы с вашим аппаратным или программным обеспечением.
Ну во-превых в KDE всё как у людей, есть просто D-BUS на ивенты которого мы подписываемся и получаем Layouts, по сути можно это даже в bash отслеживать индекс лейаута.
$ qdbus6 org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayout
0
$ qdbus6 org.kde.keyboard /Layouts org.kde.KeyboardLayouts.getLayout
1
Ну, это было, пожалуй, самым простым, а что там с клавиатурой то самой? Ну естественно умные люди всё там сделали правильно, есть стандартный протокол, есть библиотеки, инструменты, короче никаких велосипедов.
Так что там под капотом?
Да чёрт его знает, я лишь примерно представляю что там за протокол, и не занимался его отладкой, но если сильно интересно, то вот можете почитать )))
Протокол передачи цветов на клавиатуру
HID Raw — транспортный уровень
Клавиатуры с прошивкой VIA/Vial используют HID Raw interface для обмена данными:
Usage Page: 0xFF60 (vendor-defined)
Usage: 0x61
Размер пакета: 32 байта
Это стандартный интерфейс VIA, который позволяет обходить обычный HID keyboard протокол и напрямую общаться с прошивкой.
Два протокола управления RGB
1. VIA RGB Matrix (stock прошивка)
Используется для глобального цвета на всех клавишах:
Пакет: [0x07, 0x03, cmd, value1, value2, ...]
│ │ │
│ │ └── команда (brightness=0x01, effect=0x02, color=0x04)
│ └── канал RGB Matrix (0x03)
└── id_lighting_set_value
Пример установки цвета (protocol.go:111-120):
packet[0] = 0x07 // CmdVIASetValue
packet[1] = 0x03 // ChannelRGBMatrix
packet[2] = 0x04 // RGBMatrixColor
packet[3] = hue // H (0-255)
packet[4] = sat // S (0-255)
2. Vial RGB Direct (vial прошивка)
Позволяет управлять каждым LED отдельно (per-key RGB):
Включение режима: [0x07, 0x41, 0x01, 0x00, speed, H, S, V]
│ └── mode=1 (Direct)
└── vialrgb_set_mode
Установка LED: [0x07, 0x42, start_lo, start_hi, count, H,S,V, H,S,V, ...]
│ └── начальный индекс LED (16-bit)
└── vialrgb_direct_fastset
Один пакет вмещает до 9 LED (32-5)/3 = 9 цветов в формате HSV.
Цветовая модель
Используется HSV (0-255) в стиле QMK/Vial, а не стандартный HSV (0-360, 0-100, 0-100).
Автоопределение прошивки
При запуске программа отправляет команду vialrgb_get_number_leds (0x08, 0x43). Если ответ содержит количество LED > 0 — это Vial прошивка. Если 0 или ошибка — stock.
---
Зачем нужен hidapitester
https://github.com/todbot/hidapitester — это CLI утилита для отправки сырых HID пакетов. Он был необходим для reverse engineering и отладки:
1. Проверка доступа к устройству
hidapitester --vidpid 3434:0331 --usagePage 0xFF60 --usage 0x61 --open
Позволяет убедиться, что HID устройство открывается и udev права настроены правильно.
2. Ручная отправка команд для изучения протокола
# Запросить количество LED (проверка Vial)
hidapitester --vidpid 3434:0331 --usagePage 0xFF60 --usage 0x61 --open \
--send-output 0x08,0x43 --read-input
Это позволяло экспериментировать с командами VIA/Vial протокола:
- Понять формат пакетов
- Найти правильные command ID
- Проверить ответы клавиатуры
3. Отладка проблем
Когда Go код не работал, можно было проверить — проблема в коде или в самой клавиатуре:
# Установить красный цвет (VIA RGB Matrix)
hidapitester --vidpid 3434:0331 --usagePage 0xFF60 --usage 0x61 --open \
--send-output 0x07,0x03,0x04,0x00,0xFF --read-input
4. Документирование протокола
Результаты экспериментов с hidapitester помогли создать документацию в docs/FIRMWARE.md:190-193 для проверки работоспособности прошивки.
---
Схема взаимодействия
┌─────────────────┐ HID Raw (32 bytes) ┌──────────────────┐
│ kolor-keyboard │ ─────────────────────────▶ │ QMK/Vial │
│ (Go + go-hid) │ │ Firmware │
│ │ ◀───────────────────────── │ │
└─────────────────┘ Response └──────────────────┘
│ │
│ D-Bus │ PWM
▼ ▼
┌─────────────────┐ ┌──────────────────┐
│ KDE Plasma 6 │ │ RGB LED Matrix │
│ (раскладка) │ │ (per-key) │
└─────────────────┘ └──────────────────┘
Но если вы вдруг решите отлаживать всё руками, то вам определённо понадобится https://github.com/todbot/hidapitester, я начал с него но потом быстро скатился в чат с Claude.
Установка
Тут я постарался заморочиться, так как сам не люблю когда у софта нет нормальной дистрибуции, по этому есть сборки, есть пакеты, есть репозитории под все популярные и не очень дистрибутивы.
Подробнее есть блок про установку тут.
Можете и руками собрать, но тогда не забудьте добавить правила для udev rules (есть в репозитории scripts/udev как инструкция после выполнения discover) и установить зависимости:
deb -
libhidapi-hidraw0suse -
libhidapi-hidraw0rhel -
hidapi(находится в epel)alt linux -
libhidapiarch linux -
hidapi
Настройка
После установки у вас будет по сути только сама программа, но нужно ещё сгенерировать конфиг и создать сервис для работы в фоне.
Генерация конфига
Для генерации конфига есть отдельная команда - kolor-keyboard discover она обнаружит и идентифицирует вашу клавиатуру и сгенерирует пример конфигурации в текущий каталог в папку keyboards , для генерации уже рабочей конфигурации нужно запустить kolor-keyboard discover --global , тогда конфиг сохранится уже в стандартный путь в рабочем каталоге пользователя ~/.config/kolor-keyboard/ .
Конфигурация стоковых прошивок QMK выглядит так:
# kolor-keyboard configuration
# Generated for: Keychron Keychron V3
# Keyboard: keychron/v3/ansi_encoder
# Device: VID=3434 PID=0331, Firmware: stock
mode: mono
# Global RGB settings
brightness: 200 # 0-255
colors:
# Russian - red (flag color)
- layout: ru
color: {rgb: {r: 255, g: 0, b: 0}}
# English - blue
- layout: us
color: {hsv: {h: 170, s: 255, v: 180}}
# Fallback - green
- layout: "*"
color: {rgb: {r: 0, g: 255, b: 0}}
Стоковые прошивки не поддерживают direct mode и не позволяют управлять цветами отдельных LED по этому mode всегда mono. С помощью brightness задаётся яркость. В блоке colors список из языков с кодом лейаута и задаём цвет в rgb или hsv формате.
Если вы прошили клавиатуру на Vial прошивку, то появляется поддержка direct mode и можно уже отправлять отдельный цвет на каждую клавишу, но чтобы было удобнее рисовать ряды, нужно их разметить, а так как у всех клавиатур количество клавиш и рядов может быть разным, мы размечаем это в ручную. Выглядит это примерно так:

Вывод в консоли kolor-keyboard discover с разметкой рядов.
$ kolor-keyboard discover
╔══════════════════════════════════════════════════════════════╗
║ kolor-keyboard - Keyboard Discovery ║
╚══════════════════════════════════════════════════════════════╝
Scanning for VIA/Vial compatible keyboards...
Found 1 device(s):
[1] Keychron Keychron V3
VID: 0x3434 PID: 0x0331
Using: Keychron Keychron V3
Checking Vial support...
✓ Vial firmware detected! LED count: 87
Do you want to map LED rows for per-key RGB (draw mode)? [Y/n]:
╔══════════════════════════════════════════════════════════════╗
║ LED Mapping Tour ║
╠══════════════════════════════════════════════════════════════╣
║ Detected 87 LEDs (indices 0-86)
║ ║
║ Commands: ║
║ Enter/n - next LED (add to current row) ║
║ r - end row here (add LED and start new row) ║
║ s - skip this LED (don't add to any row) ║
║ b - go back (undo last LED) ║
║ q - quit and save ║
║ ║
║ Colors: ║
║ RED - current LED ║
║ GREEN - current row LEDs ║
║ YELLOW - saved rows (different shades per row) ║
╚══════════════════════════════════════════════════════════════╝
[Row 0] LED 0/86 (row has 0 LEDs) >
[Row 0] LED 1/86 (row has 1 LEDs) >
[Row 0] LED 2/86 (row has 2 LEDs) >
[Row 0] LED 3/86 (row has 3 LEDs) >
[Row 0] LED 4/86 (row has 4 LEDs) >
[Row 0] LED 5/86 (row has 5 LEDs) >
[Row 0] LED 6/86 (row has 6 LEDs) >
[Row 0] LED 7/86 (row has 7 LEDs) >
[Row 0] LED 8/86 (row has 8 LEDs) >
[Row 0] LED 9/86 (row has 9 LEDs) >
[Row 0] LED 10/86 (row has 10 LEDs) >
[Row 0] LED 11/86 (row has 11 LEDs) >
[Row 0] LED 12/86 (row has 12 LEDs) >
[Row 0] LED 13/86 (row has 13 LEDs) >
[Row 0] LED 14/86 (row has 14 LEDs) >
[Row 0] LED 15/86 (row has 15 LEDs) > к
[Row 0] LED 15/86 (row has 15 LEDs) > r
→ Row 0 saved: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15] (16 LEDs)На выходе для Vial прошивок используется или такой же mode: mono или уже mode: draw и тут мы можем задавать цвет каждой кнопке отдельно. Вот пример моего конфига:
# kolor-keyboard configuration
# Generated for: Keychron Keychron V3
# Keyboard: keychron/v3/ansi_encoder
# Device: VID=3434 PID=0331, Firmware: vial
mode: draw
# Global RGB settings
brightness: 180 # 0-255
# LED layout (generated by discover)
keyboard:
rows:
# Row 0 (16 LEDs)
- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
# Row 1 (17 LEDs)
- [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
# Row 2 (17 LEDs)
- [33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
# Row 3 (13 LEDs)
- [50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62]
# Row 4 (13 LEDs)
- [63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75]
# Row 5 (11 LEDs)
- [76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86]
draw:
# Russian - tricolor flag (white/blue/red)
- layout: ru
stripes:
- rows: [0, 1]
color: {rgb: {r: 255, g: 255, b: 255}} # white
- rows: [2, 3]
color: {rgb: {r: 0, g: 50, b: 255}} # blue
- rows: [4, 5]
color: {rgb: {r: 255, g: 0, b: 0}} # red
# English - blue
- layout: us
stripes:
# Синий canton (левый верхний угол, 3 ряда по 7 клавиш)
- leds: [0, 1, 2, 3, 4, 5, 6] # Row 0: ESC, F1-F6
color: {hsv: {h: 170, s: 255, v: 180}}
- leds: [16, 17, 18, 19, 20, 21, 22] # Row 1: ~, 1-6
color: {hsv: {h: 170, s: 255, v: 180}}
- leds: [33, 34, 35, 36, 37, 38, 39] # Row 2: Tab, Q-Y
color: {hsv: {h: 170, s: 255, v: 180}}
# Красные полосы (начинаются справа от canton + целые ряды)
- leds: [7, 8, 9, 10, 11, 12, 13, 14, 15] # Row 0 right: F7-Light
color: {rgb: {r: 255, g: 0, b: 0}}
- leds: [40, 41, 42, 43, 44, 45, 46, 47, 48, 49] # Row 2 right: U-PgDn
color: {rgb: {r: 255, g: 0, b: 0}}
- rows: [4] # Row 4 full: LShift-Up (LED 63-75)
color: {rgb: {r: 255, g: 0, b: 0}}
# Белые полосы
- leds: [23, 24, 25, 26, 27, 28, 29, 30, 31, 32] # Row 1 right: 7-PgUp
color: {hsv: {h: 0, s: 0, v: 255}}
- rows: [3] # Row 3 full: Caps-Enter (LED 50-62)
color: {rgb: {r: 255, g: 255, b: 255}}
- rows: [5] # Row 5 full: LCtrl-Right (LED 76-86)
color: {rgb: {r: 255, g: 255, b: 255}}
Создание сервиса
Теперь нужно создать сервис для работы в фоне, для этого тоже есть отдельная команда, создаёт локальный systemd unit в рабочем каталоге пользователя без sudo прав.
Просто выполняем kolor-keyboard service install и всё готово, есть аналогичные команды для просмотра логов сервиса, остановки и удаления.
Итого
Когда появится чуть больше времени я хочу вернуться к этому и сделать поддержку GNOME, Sway, а также macOS и Windows. На этом у меня всё 🙃.
Также я записал небольшой видео обзор на всё это дело, можете посмотреть
UPDATE
Забыл ссылку оставить 🙈
https://github.com/jidckii/kolor-keyboard
