// 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 #include namespace gkeymapper::daemon { // A raw HID report from the vendor interface. using Report = std::vector; // 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 }; 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; // 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 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). std::vector gKeyReports; // Some models must be told to stop mapping G-keys to F-keys first. bool disableBinding = false; std::vector disableCommands; }; const std::vector& profiles(); // Matching profile for vendor/product, or nullptr. const DeviceProfile* find_profile(uint16_t vendor, uint16_t product); // 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); // 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); } // namespace gkeymapper::daemon #endif // GKEYMAPPER_DAEMON_DEVICE_TABLES_H