// gKeyMapper daemon - per-model raw HID report tables. #include "device_tables.h" #include #include namespace gkeymapper::daemon { namespace { // The G910 reports are 20 bytes; set the given prefix and zero the rest. Report report20(std::initializer_list prefix) { Report report(20, 0); std::copy(prefix.begin(), prefix.end(), report.begin()); return report; } // G1..G9 press reports, ported from LogitechG910EventInterface.macroKeys. std::vector g910GKeys() { return { report20({0x11, 0xff, 0x08, 0x00, 0x01}), // G1 report20({0x11, 0xff, 0x08, 0x00, 0x02}), // G2 report20({0x11, 0xff, 0x08, 0x00, 0x04}), // G3 report20({0x11, 0xff, 0x08, 0x00, 0x08}), // G4 report20({0x11, 0xff, 0x08, 0x00, 0x10}), // G5 report20({0x11, 0xff, 0x08, 0x00, 0x20}), // G6 report20({0x11, 0xff, 0x08, 0x00, 0x40}), // G7 report20({0x11, 0xff, 0x08, 0x00, 0x80}), // G8 report20({0x11, 0xff, 0x08, 0x00, 0x00, 0x01}), // G9 }; } // "disable F-key to G-key binding" command (disableGKeys[0]). std::vector g910DisableCommands() { return {report20({0x11, 0xff, 0x08, 0x2e, 0x01})}; } DeviceProfile make_g910(const char* name, uint16_t product, bool disableBinding) { DeviceProfile profile; profile.name = name; profile.vendor = 0x046d; profile.product = product; profile.configuration = 0; profile.interfaceNumber = 1; profile.altSetting = 0; profile.gKeyReports = g910GKeys(); profile.releaseReport = report20({0x11, 0xff, 0x08, 0x00}); profile.disableBinding = disableBinding; if (disableBinding) { profile.disableCommands = g910DisableCommands(); } return profile; } } // namespace const std::vector& profiles() { // Orion Spectrum (c335) needs the disable command; the Orion Spark (c32b) // does not (mirrors disableGKeysInterface == 0 in the reference). static const std::vector list = { make_g910("Logitech G910 Orion Spectrum", 0xc335, true), make_g910("Logitech G910 Orion Spark", 0xc32b, false), }; return list; } const DeviceProfile* find_profile(uint16_t vendor, uint16_t product) { for (const DeviceProfile& profile : profiles()) { if (profile.vendor == vendor && profile.product == product) { return &profile; } } return nullptr; } int match_gkey(const DeviceProfile& profile, const uint8_t* data, int length) { if (length <= 0) { return -1; } for (size_t i = 0; i < profile.gKeyReports.size(); ++i) { const Report& report = profile.gKeyReports[i]; if (static_cast(report.size()) == length && std::equal(report.begin(), report.end(), data)) { return static_cast(i); } } return -1; } bool is_release_report(const DeviceProfile& profile, const uint8_t* data, int length) { return static_cast(profile.releaseReport.size()) == length && std::equal(profile.releaseReport.begin(), profile.releaseReport.end(), data); } } // namespace gkeymapper::daemon