Files
gKeyMapper/daemon/device_tables.h

78 lines
3.1 KiB
C
Raw Permalink Normal View History

2026-10-17 03:53:51 +02:00
// gKeyMapper daemon - per-model raw HID report tables.
//
// Ported from the byte tables of the Python reference project
// (g910_gkeys/data_mappers/supported_devices.py). Keys are matched against the
// exact bytes read from the keyboard's vendor interface.
#ifndef GKEYMAPPER_DAEMON_DEVICE_TABLES_H
#define GKEYMAPPER_DAEMON_DEVICE_TABLES_H
#include <cstdint>
#include <vector>
namespace gkeymapper::daemon {
// A raw HID report from the vendor interface.
using Report = std::vector<uint8_t>;
2026-10-18 03:50:33 +02:00
// One media key: the bit it has in the media report and the Linux input code it
// is replayed as.
struct MediaKey {
uint8_t bit = 0;
uint16_t key = 0; // Linux KEY_* code
const char* name = ""; // for the log line
};
2026-10-17 03:53:51 +02:00
struct DeviceProfile {
const char* name = "";
uint16_t vendor = 0;
uint16_t product = 0;
int configuration = 0; // 0-based configuration index
int interfaceNumber = 1;
int altSetting = 0;
2026-10-18 03:50:33 +02:00
// Media keys (mute / volume / play) arrive as a short report: this prefix
// byte followed by one bit per key, 0 when they are all released. 0 means
// the model reports none. This is the only path the keyboard offers for
// those keys, so while the daemon holds the interface the kernel does not see
// them at all — the daemon replays them through its virtual keyboard.
uint8_t mediaPrefix = 0;
std::vector<MediaKey> mediaKeys;
// gKeyReports[i] is the report that has the bit of G(i+1) set. Both the
// shared header bytes and the bit of each key are derived from these, so a
// new model only needs its table (see decode_gkey_state).
2026-10-17 03:53:51 +02:00
std::vector<Report> gKeyReports;
// Some models must be told to stop mapping G-keys to F-keys first.
bool disableBinding = false;
std::vector<Report> disableCommands;
};
const std::vector<DeviceProfile>& profiles();
// Matching profile for vendor/product, or nullptr.
const DeviceProfile* find_profile(uint16_t vendor, uint16_t product);
2026-10-18 03:50:33 +02:00
// Decodes a macro-key report into the keys it reports as pressed: bit 0 = G1 ..
// bit 8 = G9. Returns false for every other report — the media keys have their
// own decoder below, and memory keys, LED and command acknowledgements are
// ignored on purpose.
//
// The report carries the state of all G keys, not a single key: one report with
// several bits set means a chord, and "no bit set" is the release. The caller
// compares consecutive states, which makes a held key (repeating report) fire
// once and a chord fire every key it contains.
bool decode_gkey_state(const DeviceProfile& profile, const uint8_t* data, int length,
uint32_t& pressed);
2026-10-17 03:53:51 +02:00
2026-10-18 03:50:33 +02:00
// Decodes a media-key report into its bits (bit set = key held), using the bit
// table of the profile. `bits` is 0 for the release report, which is a valid
// media report. Returns false for every other report, in particular for the
// macro-key reports.
bool decode_media_key(const DeviceProfile& profile, const uint8_t* data, int length,
uint32_t& bits);
2026-10-17 03:53:51 +02:00
} // namespace gkeymapper::daemon
#endif // GKEYMAPPER_DAEMON_DEVICE_TABLES_H