diff --git a/makefile b/makefile index 6102514..b28bff7 100644 --- a/makefile +++ b/makefile @@ -64,6 +64,7 @@ setup: @test -s $(DESTDIR)/usr/bin/g512-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g512-led @test -s $(DESTDIR)/usr/bin/g513-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g513-led @test -s $(DESTDIR)/usr/bin/g610-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g610-led + @test -s $(DESTDIR)/usr/bin/g815-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g815-led @test -s $(DESTDIR)/usr/bin/g910-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g910-led @test -s $(DESTDIR)/usr/bin/gpro-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/gpro-led @cp sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples @@ -111,6 +112,7 @@ uninstall: @rm /usr/bin/g512-led @rm /usr/bin/g513-led @rm /usr/bin/g610-led + @rm /usr/bin/g815-led @rm /usr/bin/g910-led @rm /usr/bin/gpro-led @rm /usr/bin/$(PROGN) diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index c5acf2c..f4aa4fd 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(hidapi) #include @@ -378,10 +379,12 @@ bool LedKeyboard::commit() { case KeyboardModel::g513: case KeyboardModel::g610: case KeyboardModel::g810: - case KeyboardModel::g815: case KeyboardModel::gpro: data = { 0x11, 0xff, 0x0c, 0x5a }; break; + case KeyboardModel::g815: + data = { 0x11, 0xff, 0x10, 0x7f }; + break; case KeyboardModel::g910: data = { 0x11, 0xff, 0x0f, 0x5d }; break; @@ -401,136 +404,228 @@ bool LedKeyboard::setKeys(KeyValueArray keyValues) { bool retval = true; - vector> SortedKeys = { - {}, // Logo AddressGroup - {}, // Indicators AddressGroup - {}, // Multimedia AddressGroup - {}, // GKeys AddressGroup - {} // Keys AddressGroup - }; + vector> SortedKeys; + map> KeyByColors; + map>::iterator KeyByColorsIterator; + const uint8_t maxKeyPerColor = 13; - for (uint8_t i = 0; i < keyValues.size(); i++) { - switch(static_cast(static_cast(keyValues[i].key) >> 8 )) { - case LedKeyboard::KeyAddressGroup::logo: - switch (currentDevice.model) { - case LedKeyboard::KeyboardModel::g610: - case LedKeyboard::KeyboardModel::g810: - case LedKeyboard::KeyboardModel::gpro: - if (SortedKeys[0].size() <= 1 && keyValues[i].key == LedKeyboard::Key::logo) - SortedKeys[0].push_back(keyValues[i]); - break; - case LedKeyboard::KeyboardModel::g910: - if (SortedKeys[0].size() <= 2) SortedKeys[0].push_back(keyValues[i]); - break; - default: - break; - } - break; - case LedKeyboard::KeyAddressGroup::indicators: - if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]); - break; - case LedKeyboard::KeyAddressGroup::multimedia: - switch (currentDevice.model) { - case LedKeyboard::KeyboardModel::g610: - case LedKeyboard::KeyboardModel::g810: - case LedKeyboard::KeyboardModel::gpro: - if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); - break; - default: - break; - } - break; - case LedKeyboard::KeyAddressGroup::gkeys: - switch (currentDevice.model) { - case LedKeyboard::KeyboardModel::g910: - if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); - break; - default: - break; - } - break; - case LedKeyboard::KeyAddressGroup::keys: - switch (currentDevice.model) { - case LedKeyboard::KeyboardModel::g512: - case LedKeyboard::KeyboardModel::g513: - case LedKeyboard::KeyboardModel::g610: - case LedKeyboard::KeyboardModel::g810: - case LedKeyboard::KeyboardModel::g910: - case LedKeyboard::KeyboardModel::gpro: - if (SortedKeys[4].size() <= 120) SortedKeys[4].push_back(keyValues[i]); - break; - case LedKeyboard::KeyboardModel::g410: - if (SortedKeys[4].size() <= 120) - if (keyValues[i].key < LedKeyboard::Key::num_lock || - keyValues[i].key > LedKeyboard::Key::num_dot) - SortedKeys[4].push_back(keyValues[i]); - break; - default: - break; - } - break; - } - } - - for (uint8_t kag = 0; kag < 5; kag++) { - - if (SortedKeys[kag].size() > 0) { - - uint8_t gi = 0; - while (gi < SortedKeys[kag].size()) { - - size_t data_size = 0; - byte_buffer_t data = {}; - - switch (kag) { - case 0: - data_size = 20; - data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::logo); - break; - case 1: - data_size = 64; - data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::indicators); - break; - case 2: - data_size = 64; - data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::multimedia); - break; - case 3: - data_size = 64; - data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::gkeys); - break; - case 4: - data_size = 64; - data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::keys); - break; - } - - const uint8_t maxKeyCount = (data_size - 8) / 4; - - if (data.size() > 0) { - - for (uint8_t i = 0; i < maxKeyCount; i++) { - if (gi + i < SortedKeys[kag].size()) { - data.push_back(static_cast( - static_cast(SortedKeys[kag][gi+i].key) & 0x00ff)); - data.push_back(SortedKeys[kag][gi+i].color.red); - data.push_back(SortedKeys[kag][gi+i].color.green); - data.push_back(SortedKeys[kag][gi+i].color.blue); - } - } - - data.resize(data_size, 0x00); - - if (retval) retval = sendDataInternal(data); - else sendDataInternal(data); - - } - - gi = gi + maxKeyCount; + switch (currentDevice.model) { + case KeyboardModel::g815: + for (uint8_t i = 0; i < keyValues.size(); i++) { + uint32_t colorkey = static_cast(keyValues[i].color.red | keyValues[i].color.green << 8 | keyValues[i].color.blue << 16 ); + if (KeyByColors.count(colorkey) == 0) KeyByColors.insert(pair>(colorkey, {})); + KeyByColors[colorkey].push_back(keyValues[i]); } - } + for (auto& x: KeyByColors) { + if (x.second.size() > 0) { + uint8_t gi = 0; + while (gi < x.second.size()) { + size_t data_size = 20; + byte_buffer_t data = { 0x11, 0xff, 0x10, 0x6c }; + data.push_back(x.second[0].color.red); + data.push_back(x.second[0].color.green); + data.push_back(x.second[0].color.blue); + for (uint8_t i = 0; i < maxKeyPerColor; i++) { + if (gi + i < x.second.size()) { + switch (x.second[gi+i].key) { + case Key::logo2: + case Key::game: + case Key::caps: + case Key::scroll: + case Key::num: + case Key::stop: + case Key::g6: + case Key::g7: + case Key::g8: + case Key::g9: + break; + case Key::play: + data.push_back(0x9b); + break; + case Key::mute: + data.push_back(0x9c); + break; + case Key::next: + data.push_back(0x9d); + break; + case Key::prev: + data.push_back(0x9e); + break; + case Key::ctrl_left: + case Key::shift_left: + case Key::alt_left: + case Key::win_left: + case Key::ctrl_right: + case Key::shift_right: + case Key::alt_right: + case Key::win_right: + data.push_back((static_cast(x.second[gi+i].key) & 0x00ff) - 0x78); + break; + default: + switch (static_cast((static_cast(x.second[gi+i].key) & 0xff00) / 0xff)) { + case KeyAddressGroup::logo: + data.push_back((static_cast(x.second[gi+i].key) & 0x00ff) + 0xd1); + break; + case KeyAddressGroup::indicators: + data.push_back((static_cast(x.second[gi+i].key) & 0x00ff) + 0x98); + break; + case KeyAddressGroup::gkeys: + data.push_back((static_cast(x.second[gi+i].key) & 0x00ff) + 0xb3); + break; + case KeyAddressGroup::keys: + data.push_back((static_cast(x.second[gi+i].key) & 0x00ff) - 0x03); + break; + default: + break; + } + } + } + } + + if (data.size() < data_size) data.push_back(0xff); + data.resize(data_size, 0x00); + if (retval) retval = sendDataInternal(data); + else sendDataInternal(data); + + gi = gi + maxKeyPerColor; + } + } + } + + break; + default: + SortedKeys = { + {}, // Logo AddressGroup + {}, // Indicators AddressGroup + {}, // Multimedia AddressGroup + {}, // GKeys AddressGroup + {} // Keys AddressGroup + }; + + for (uint8_t i = 0; i < keyValues.size(); i++) { + switch(static_cast(static_cast(keyValues[i].key) >> 8 )) { + case LedKeyboard::KeyAddressGroup::logo: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[0].size() <= 1 && keyValues[i].key == LedKeyboard::Key::logo) + SortedKeys[0].push_back(keyValues[i]); + break; + case LedKeyboard::KeyboardModel::g910: + if (SortedKeys[0].size() <= 2) SortedKeys[0].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::indicators: + if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::multimedia: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::gkeys: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g910: + if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::keys: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g513: + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::g910: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[4].size() <= 120) SortedKeys[4].push_back(keyValues[i]); + break; + case LedKeyboard::KeyboardModel::g410: + if (SortedKeys[4].size() <= 120) + if (keyValues[i].key < LedKeyboard::Key::num_lock || + keyValues[i].key > LedKeyboard::Key::num_dot) + SortedKeys[4].push_back(keyValues[i]); + break; + default: + break; + } + break; + } + } + + for (uint8_t kag = 0; kag < 5; kag++) { + + if (SortedKeys[kag].size() > 0) { + + uint8_t gi = 0; + while (gi < SortedKeys[kag].size()) { + + size_t data_size = 0; + byte_buffer_t data = {}; + + switch (kag) { + case 0: + data_size = 20; + data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::logo); + break; + case 1: + data_size = 64; + data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::indicators); + break; + case 2: + data_size = 64; + data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::multimedia); + break; + case 3: + data_size = 64; + data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::gkeys); + break; + case 4: + data_size = 64; + data = getKeyGroupAddress(LedKeyboard::KeyAddressGroup::keys); + break; + } + + const uint8_t maxKeyCount = (data_size - 8) / 4; + + if (data.size() > 0) { + + for (uint8_t i = 0; i < maxKeyCount; i++) { + if (gi + i < SortedKeys[kag].size()) { + data.push_back(static_cast( + static_cast(SortedKeys[kag][gi+i].key) & 0x00ff)); + data.push_back(SortedKeys[kag][gi+i].color.red); + data.push_back(SortedKeys[kag][gi+i].color.green); + data.push_back(SortedKeys[kag][gi+i].color.blue); + } + } + + data.resize(data_size, 0x00); + + if (retval) retval = sendDataInternal(data); + else sendDataInternal(data); + + } + + gi = gi + maxKeyCount; + } + + } + } } + return retval; } @@ -544,12 +639,7 @@ bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) { keyArray = keyGroupLogo; break; case KeyGroup::indicators: - switch (currentDevice.model) { - case KeyboardModel::g815: - return true; - default: - keyArray = keyGroupIndicators; - } + keyArray = keyGroupIndicators; break; case KeyGroup::gkeys: keyArray = keyGroupGKeys; @@ -596,10 +686,11 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { NativeEffectStorage::none); return true; case KeyboardModel::g410: - case KeyboardModel::g512: - case KeyboardModel::g513: + case KeyboardModel::g512: + case KeyboardModel::g513: case KeyboardModel::g610: case KeyboardModel::g810: + case KeyboardModel::g815: case KeyboardModel::g910: case KeyboardModel::gpro: for (uint8_t i = 0; i < keyGroupLogo.size(); i++) keyValues.push_back({keyGroupLogo[i], color}); @@ -623,6 +714,17 @@ bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { bool LedKeyboard::setMRKey(uint8_t value) { LedKeyboard::byte_buffer_t data; switch (currentDevice.model) { + case KeyboardModel::g815: + switch (value) { + case 0x00: + case 0x01: + data = { 0x11, 0xff, 0x0c, 0x0c, value }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; case KeyboardModel::g910: switch (value) { case 0x00: @@ -643,6 +745,24 @@ bool LedKeyboard::setMRKey(uint8_t value) { bool LedKeyboard::setMNKey(uint8_t value) { LedKeyboard::byte_buffer_t data; switch (currentDevice.model) { + case KeyboardModel::g815: + switch (value) { + case 0x01: + data = { 0x11, 0xff, 0x0b, 0x1c, 0x01 }; + data.resize(20, 0x00); + return sendDataInternal(data); + case 0x02: + data = { 0x11, 0xff, 0x0b, 0x1c, 0x02 }; + data.resize(20, 0x00); + return sendDataInternal(data); + case 0x03: + data = { 0x11, 0xff, 0x0b, 0x1c, 0x04 }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; case KeyboardModel::g910: switch (value) { case 0x00: @@ -669,6 +789,17 @@ bool LedKeyboard::setMNKey(uint8_t value) { bool LedKeyboard::setGKeysMode(uint8_t value) { LedKeyboard::byte_buffer_t data; switch (currentDevice.model) { + case KeyboardModel::g815: + switch (value) { + case 0x00: + case 0x01: + data = { 0x11, 0xff, 0x0a, 0x2b, value }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; case KeyboardModel::g910: switch (value) { case 0x00: @@ -722,6 +853,17 @@ bool LedKeyboard::setStartupMode(StartupMode startupMode) { return sendDataInternal(data); } +bool LedKeyboard::setOnBoardMode(OnBoardMode onBoardMode) { + byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g815: + data = { 0x11, 0xff, 0x11, 0x1a, static_cast(onBoardMode) }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + return false; + } +} bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, std::chrono::duration period, Color color, @@ -945,6 +1087,20 @@ LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddre return { 0x12, 0xff, 0x0c, 0x3a, 0x00, 0x01, 0x00, 0x0e }; } break; + case KeyboardModel::g815: + switch (keyAddressGroup) { + case LedKeyboard::KeyAddressGroup::logo: + return { 0x11, 0xff, 0x10, 0x1c }; + case LedKeyboard::KeyAddressGroup::indicators: + return { 0x11, 0xff, 0x10, 0x1c }; + case LedKeyboard::KeyAddressGroup::gkeys: + return { 0x11, 0xff, 0x10, 0x1c }; + case LedKeyboard::KeyAddressGroup::multimedia: + return { 0x11, 0xff, 0x10, 0x1c }; + case LedKeyboard::KeyAddressGroup::keys: + return { 0x11, 0xff, 0x10, 0x1c }; + } + break; case KeyboardModel::g910: switch (keyAddressGroup) { case LedKeyboard::KeyAddressGroup::logo: diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index 596716e..ccb2837 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -80,6 +80,10 @@ class LedKeyboard { wave = 0x01, color }; + enum class OnBoardMode : uint8_t { + board = 0x01, + software + }; enum class NativeEffectGroup : uint8_t { off, color, @@ -203,6 +207,7 @@ class LedKeyboard { bool setRegion(uint8_t region, Color color); bool setStartupMode(StartupMode startupMode); + bool setOnBoardMode(OnBoardMode onBoardMode); bool setNativeEffect(NativeEffect effect, NativeEffectPart part, std::chrono::duration period, Color color, diff --git a/src/helpers/help.cpp b/src/helpers/help.cpp index 36548d1..aac491a 100644 --- a/src/helpers/help.cpp +++ b/src/helpers/help.cpp @@ -36,6 +36,7 @@ namespace help { else if(cmdName == "g513-led") return KeyboardFeatures::g513; else if(cmdName == "g610-led") return KeyboardFeatures::g610; else if(cmdName == "g810-led") return KeyboardFeatures::g810; + else if(cmdName == "g815-led") return KeyboardFeatures::g815; else if(cmdName == "g910-led") return KeyboardFeatures::g910; else if(cmdName == "gpro-led") return KeyboardFeatures::gpro; return KeyboardFeatures::all; @@ -90,6 +91,10 @@ namespace help { cout<<" --startup-mode {startup mode}\t\tSet startup mode"< 1) { if (setGKeysMode(kbd, args[1]) == 1) retval = 1; + } else if (args[0] == "sm" && args.size() > 1) { + if (setStartupMode(kbd, args[1]) == 1) retval = 1; + } else if (args[0] == "obm" && args.size() > 1) { + if (setOnBoardMode(kbd, args[1]) == 1) retval = 1; } else if (args[0] == "fx" && args.size() > 4) { if (setFX(kbd, args[1], args[2], args[3], args[4]) == 1) retval = 1; } else if (args[0] == "fx" && args.size() > 3) { @@ -337,6 +349,7 @@ int main(int argc, char **argv) { else if (argc > (argIndex + 3) && arg == "-fx-store") return storeFX(kbd, argv[argIndex + 1], argv[argIndex + 2], argv[argIndex + 3]); else if (argc > (argIndex + 1) && arg == "--startup-mode") return setStartupMode(kbd, argv[argIndex + 1]); + else if (argc > (argIndex + 1) && arg == "--on-board-mode") return setOnBoardMode(kbd, argv[argIndex + 1]); else { help::usage(argv[0]); return 1; } } diff --git a/udev/g810-led.rules b/udev/g810-led.rules index d123e18..90b743b 100644 --- a/udev/g810-led.rules +++ b/udev/g810-led.rules @@ -7,6 +7,7 @@ ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c3 ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c338", MODE="666" RUN+="/usr/bin/g610-led -p /etc/g810-led/profile" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c33f", MODE="666" RUN+="/usr/bin/g815-led -p /etc/g810-led/profile" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile" ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c339", MODE="666" RUN+="/usr/bin/gpro-led -p /etc/g810-led/profile"