diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e31e806 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +g810-led.* +bin/* +. diff --git a/INSTALL.md b/INSTALL.md index e098e84..21bfb55 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -14,10 +14,8 @@ ArchLinux :
`sudo pacman -S git gcc make libusb`
Debian :
`sudo apt-get install git g++ make libusb-1.0-0-dev`
-OpenSUSE :
-`sudo zypper in git make gcc-c++ libstdc++-devel libusb-1_0-devel`
-CentOS :
-`sudo yum install git make gcc-c++ libstdc++-devel libusb-devel`
+Fedora :
+`sudo dnf install git make gcc-c++ libusb-devel`
## Installation :
`git clone https://github.com/MatMoul/g810-led.git`
diff --git a/README.md b/README.md index 3b196cc..fdea43b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Linux LED controller for Logitech Led Keyboards.
- **G910 Orion Spectrum**
##Install and use :
-* https://github.com/MatMoul/g810-led/blob/master/INSTALL.md +* INSTALL.md ##Help :
`g410-led --help`
@@ -25,12 +25,12 @@ Linux LED controller for Logitech Led Keyboards.
`g810-led -a 00ff00 # Set color of all keys`
`g810-led -g fkeys ff00ff # Set color of a group of keys`
`g810-led -s color # Set keyboard power on effect`
-`g810-led -fx-color 00ff00 # Set fixed color effect`
-`g810-led -fx-breathing 00ff00 0a # Set breathing effect`
-`g810-led -fx-cycle 0a # Set color cycle effect`
-`g810-led -fx-hwave 0a # Set horizontal wave effect`
-`g810-led -fx-vwave 0a # Set vertical wave effect`
-`g810-led -fx-cwave 0a # Set center wave effect`
+`g810-led -fx color keys 00ff00 # Set fixed color effect`
+`g810-led -fx breathing logo 00ff00 0a # Set breathing effect`
+`g810-led -fx cycle all 0a # Set color cycle effect`
+`g810-led -fx hwave keys 0a # Set horizontal wave effect`
+`g810-led -fx vwave keys 0a # Set vertical wave effect`
+`g810-led -fx cwave keys 0a # Set center wave effect`
##Samples with no commit :
`g810-led -an 000000 # Set color of all key with no action`
diff --git a/makefile b/makefile index f393534..917f0bc 100644 --- a/makefile +++ b/makefile @@ -1,24 +1,23 @@ CC=g++ CFLAGS=-Wall -O2 -std=gnu++11 -LIBUSB_INC?=-I/usr/include/libusb-1.0 LDFLAGS=-lusb-1.0 PROGN=g810-led SYSTEMDDIR?=/usr/lib/systemd -.PHONY: all debug clean install uninstall +.PHONY: all debug clean all: bin/$(PROGN) -bin/$(PROGN): src/main.cpp src/classes/*.cpp src/classes/*.h +bin/$(PROGN): src/main.cpp src/helpers/*.cpp src/helpers/*.h src/classes/*.cpp src/classes/*.h @mkdir -p bin - $(CC) $(CFLAGS) $(LIBUSB_INC) -o $@ $^ $(LDFLAGS) - + $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + debug: CFLAGS += -g -Wextra -pedantic debug: bin/$(PROGN) - + clean: @rm -rf bin - + install: @install -m 755 -d \ $(DESTDIR)/etc/$(PROGN)/samples \ diff --git a/pictures/g410.png b/pictures/g410.png deleted file mode 100644 index 6032224..0000000 Binary files a/pictures/g410.png and /dev/null differ diff --git a/pictures/g610.png b/pictures/g610.png deleted file mode 100644 index f734ac6..0000000 Binary files a/pictures/g610.png and /dev/null differ diff --git a/pictures/g810.jpg b/pictures/g810.jpg deleted file mode 100644 index 0cb5d34..0000000 Binary files a/pictures/g810.jpg and /dev/null differ diff --git a/pictures/g910.jpg b/pictures/g910.jpg deleted file mode 100644 index 3a0c414..0000000 Binary files a/pictures/g910.jpg and /dev/null differ diff --git a/sample_profiles/all_blue_fxl_breathing_red b/sample_profiles/all_blue_fxl_breathing_red index 0898d67..8e8ccf4 100644 --- a/sample_profiles/all_blue_fxl_breathing_red +++ b/sample_profiles/all_blue_fxl_breathing_red @@ -2,4 +2,4 @@ a 0000ff # Set all keys blue c # Commit changes -fxl-breathing ff0000 10 # Set breathing effect with red color and speed 10 +fx breathing logo ff0000 10 # Set breathing effect with red color and speed 10 diff --git a/sample_profiles/fx_breathing_red b/sample_profiles/fx_breathing_red index 1b0be0b..250349c 100644 --- a/sample_profiles/fx_breathing_red +++ b/sample_profiles/fx_breathing_red @@ -1,2 +1,2 @@ -fx-breathing ff0000 10 # Set breathing effect with red color and speed 10 +fx breathing all ff0000 20 # Set breathing effect with red color and speed 20 diff --git a/sample_profiles/fx_color_green b/sample_profiles/fx_color_green index 05f8232..97264a7 100644 --- a/sample_profiles/fx_color_green +++ b/sample_profiles/fx_color_green @@ -1,3 +1,3 @@ # Green Profile -fx-color 00ff00 # Set all keys green +fx color all 00ff00 # Set all keys green diff --git a/sample_profiles/fx_cwave b/sample_profiles/fx_cwave index 3405986..347a1bc 100644 --- a/sample_profiles/fx_cwave +++ b/sample_profiles/fx_cwave @@ -1,2 +1,2 @@ -fx-cwave 10 # Set center wave effect with speed 10 +fx cwave all 20 # Set center wave effect with speed 20 diff --git a/sample_profiles/fx_cycle b/sample_profiles/fx_cycle new file mode 100644 index 0000000..249adcb --- /dev/null +++ b/sample_profiles/fx_cycle @@ -0,0 +1,2 @@ + +fx cycle all 20 # Set color cycle effect with speed 20 diff --git a/sample_profiles/fx_hwave b/sample_profiles/fx_hwave index 5eb537c..cea0f8a 100644 --- a/sample_profiles/fx_hwave +++ b/sample_profiles/fx_hwave @@ -1,2 +1,2 @@ -fx-hwave 10 # Set horizontal wave effect with speed 10 +fx hwave all 20 # Set horizontal wave effect with speed 20 diff --git a/sample_profiles/fx_vwave b/sample_profiles/fx_vwave index 30ea410..a52aca2 100644 --- a/sample_profiles/fx_vwave +++ b/sample_profiles/fx_vwave @@ -1,2 +1,2 @@ -fx-vwave 10 # Set vertical wave effect with speed 10 +fx vwave all 20 # Set vertical wave effect with speed 20 diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index b52636c..1a37ca1 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -1,1101 +1,490 @@ #include "Keyboard.h" -#include + +#include #include -#include -#include "libusb.h" +#include + +#include "libusb-1.0/libusb.h" -bool Keyboard::isAttached() { - return m_isAttached; +using namespace std; + + + +LedKeyboard::~LedKeyboard() { + close(); } -bool Keyboard::attach() { - if (m_isAttached == true) return false; - int r; - r = libusb_init(&ctx); - if (r < 0) return false; + +bool LedKeyboard::listKeyboards() { + libusb_context *ctx = NULL; + if(libusb_init(&m_ctx) < 0) return false; libusb_device **devs; ssize_t cnt = libusb_get_device_list(ctx, &devs); - if(cnt < 0) return false; - int pid = 0; - for(ssize_t i = 0; i < cnt; i++) { - libusb_device *device = devs[i]; - libusb_device_descriptor desc = { - 0, // bLength - 0, // bDescriptorType - 0, // bcdUSB - 0, // bDeviceClass - 0, // bDeviceSubClass - 0, // bDeviceProtocol - 0, // bMaxPacketSize0 - 0, // idVendor - 0, // idProduct - 0, // bcdDevice - 0, // iManufacturer - 0, // iProduct - 0, // iSerialNumber - 0 // bNumConfigurations - }; - libusb_get_device_descriptor(device, &desc); - if (desc.idVendor == 0x046d) { - if (desc.idProduct == 0xc331) { pid = desc.idProduct; break; } // G810 spectrum - if (desc.idProduct == 0xc337) { pid = desc.idProduct; break; } // G810 spectrum - if (desc.idProduct == 0xc330) { pid = desc.idProduct; break; } // G410 spectrum - if (desc.idProduct == 0xc333) { pid = desc.idProduct; break; } // G610 spectrum - if (desc.idProduct == 0xc338) { pid = desc.idProduct; break; } // G610 spectrum - if (desc.idProduct == 0xc32b) { // G910 spark - pid = desc.idProduct; - kbdProtocol = KeyboardProtocol::g910; - break; - } - if (desc.idProduct == 0xc335) { // G910 spectrum - pid = desc.idProduct; - kbdProtocol = KeyboardProtocol::g910; - break; + if(cnt >= 0) { + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor desc = { + 0, // bLength + 0, // bDescriptorType + 0, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + 0, // bMaxPacketSize0 + 0, // idVendor + 0, // idProduct + 0, // bcdDevice + 0, // iManufacturer + 0, // iProduct + 0, // iSerialNumber + 0 // bNumConfigurations + }; + libusb_get_device_descriptor(device, &desc); + for (int i=0; i<(int)SuportedKeyboards.size(); i++) { + if (desc.idVendor == SuportedKeyboards[i][0]) { + if (desc.idProduct == SuportedKeyboards[i][1]) { + cout<<"0x"<= 0) { + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor desc = { + 0, // bLength + 0, // bDescriptorType + 0, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + 0, // bMaxPacketSize0 + 0, // idVendor + 0, // idProduct + 0, // bcdDevice + 0, // iManufacturer + 0, // iProduct + 0, // iSerialNumber + 0 // bNumConfigurations + }; + libusb_get_device_descriptor(device, &desc); + for (int i=0; i<(int)SuportedKeyboards.size(); i++) { + if (desc.idVendor == SuportedKeyboards[i][0]) { + if (desc.idProduct == SuportedKeyboards[i][1]) { + m_vendorID = desc.idVendor; + m_productID = desc.idProduct; + m_keyboardModel = (KeyboardModel)SuportedKeyboards[i][2]; + break; + } + } + } + + if (m_keyboardModel != KeyboardModel::unknown) break; + + } + libusb_free_device_list(devs, 1); + } } - libusb_free_device_list(devs, 1); - if (pid == 0) { - libusb_exit(ctx); - ctx = NULL; + + if (m_keyboardModel == KeyboardModel::unknown) { + cout<<"Keyboard not found"<> 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: + if (SortedKeys[0].size() <= 2) SortedKeys[0].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::indicators: + if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::multimedia: + if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::gkeys: + if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::keys: + if (SortedKeys[4].size() <= 120) SortedKeys[4].push_back(keyValues[i]); + 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; } -bool Keyboard::getKeyAddress(Key key, KeyAddress &keyAddress) { - switch (key) { - case Key::logo: - keyAddress.addressGroup = KeyAddressGroup::logo; - keyAddress.id = 0x01; +bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) { + KeyValueArray keyValues; + + KeyArray keyArray; + + switch (keyGroup) { + case KeyGroup::logo: + keyArray = keyGroupLogo; break; - case Key::logo2: - keyAddress.addressGroup = KeyAddressGroup::logo; - keyAddress.id = 0x02; + case KeyGroup::indicators: + keyArray = keyGroupIndicators; break; - case Key::backlight: - keyAddress.addressGroup = KeyAddressGroup::indicators; - keyAddress.id = 0x01; + case KeyGroup::gkeys: + keyArray = keyGroupGKeys; break; - case Key::game: - keyAddress.addressGroup = KeyAddressGroup::indicators; - keyAddress.id = 0x02; + case KeyGroup::multimedia: + keyArray = keyGroupMultimedia; break; - case Key::caps: - keyAddress.addressGroup = KeyAddressGroup::indicators; - keyAddress.id = 0x03; + case KeyGroup::fkeys: + keyArray = keyGroupFKeys; break; - case Key::scroll: - keyAddress.addressGroup = KeyAddressGroup::indicators; - keyAddress.id = 0x04; + case KeyGroup::modifiers: + keyArray = keyGroupModifiers; break; - case Key::num: - keyAddress.addressGroup = KeyAddressGroup::indicators; - keyAddress.id = 0x05; + case KeyGroup::arrows: + keyArray = keyGroupArrows; break; - case Key::next: - keyAddress.addressGroup = KeyAddressGroup::multimedia; - keyAddress.id = 0xb5; + case KeyGroup::numeric: + keyArray = keyGroupNumeric; break; - case Key::prev: - keyAddress.addressGroup = KeyAddressGroup::multimedia; - keyAddress.id = 0xb6; + case KeyGroup::functions: + keyArray = keyGroupFunctions; break; - case Key::stop: - keyAddress.addressGroup = KeyAddressGroup::multimedia; - keyAddress.id = 0xb7; - break; - case Key::play: - keyAddress.addressGroup = KeyAddressGroup::multimedia; - keyAddress.id = 0xcd; - break; - case Key::mute: - keyAddress.addressGroup = KeyAddressGroup::multimedia; - keyAddress.id = 0xe2; - break; - case Key::g1: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x01; - break; - case Key::g2: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x02; - break; - case Key::g3: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x03; - break; - case Key::g4: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x04; - break; - case Key::g5: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x05; - break; - case Key::g6: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x06; - break; - case Key::g7: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x07; - break; - case Key::g8: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x08; - break; - case Key::g9: - keyAddress.addressGroup = KeyAddressGroup::gkeys; - keyAddress.id = 0x09; + case KeyGroup::keys: + keyArray = keyGroupKeys; break; default: - keyAddress.addressGroup = KeyAddressGroup::keys; - switch (key) { - case Key::a: keyAddress.id = 0x04; break; - case Key::b: keyAddress.id = 0x05; break; - case Key::c: keyAddress.id = 0x06; break; - case Key::d: keyAddress.id = 0x07; break; - case Key::e: keyAddress.id = 0x08; break; - case Key::f: keyAddress.id = 0x09; break; - case Key::g: keyAddress.id = 0x0a; break; - case Key::h: keyAddress.id = 0x0b; break; - case Key::i: keyAddress.id = 0x0c; break; - case Key::j: keyAddress.id = 0x0d; break; - case Key::k: keyAddress.id = 0x0e; break; - case Key::l: keyAddress.id = 0x0f; break; - case Key::m: keyAddress.id = 0x10; break; - case Key::n: keyAddress.id = 0x11; break; - case Key::o: keyAddress.id = 0x12; break; - case Key::p: keyAddress.id = 0x13; break; - case Key::q: keyAddress.id = 0x14; break; - case Key::r: keyAddress.id = 0x15; break; - case Key::s: keyAddress.id = 0x16; break; - case Key::t: keyAddress.id = 0x17; break; - case Key::u: keyAddress.id = 0x18; break; - case Key::v: keyAddress.id = 0x19; break; - case Key::w: keyAddress.id = 0x1a; break; - case Key::x: keyAddress.id = 0x1b; break; - case Key::y: keyAddress.id = 0x1c; break; - case Key::z: keyAddress.id = 0x1d; break; - case Key::n1: keyAddress.id = 0x1e; break; - case Key::n2: keyAddress.id = 0x1f; break; - case Key::n3: keyAddress.id = 0x20; break; - case Key::n4: keyAddress.id = 0x21; break; - case Key::n5: keyAddress.id = 0x22; break; - case Key::n6: keyAddress.id = 0x23; break; - case Key::n7: keyAddress.id = 0x24; break; - case Key::n8: keyAddress.id = 0x25; break; - case Key::n9: keyAddress.id = 0x26; break; - case Key::n0: keyAddress.id = 0x27; break; - case Key::enter: keyAddress.id = 0x28; break; - case Key::esc: keyAddress.id = 0x29; break; - case Key::backspace: keyAddress.id = 0x2a; break; - case Key::tab: keyAddress.id = 0x2b; break; - case Key::space: keyAddress.id = 0x2c; break; - case Key::minus: keyAddress.id = 0x2d; break; - case Key::equal: keyAddress.id = 0x2e; break; - case Key::open_bracket: keyAddress.id = 0x2f; break; - case Key::close_bracket: keyAddress.id = 0x30; break; - case Key::backslash: keyAddress.id = 0x31; break; - case Key::dollar: keyAddress.id = 0x32; break; - case Key::semicolon: keyAddress.id = 0x33; break; - case Key::quote: keyAddress.id = 0x34; break; - case Key::tilde: keyAddress.id = 0x35; break; - case Key::comma: keyAddress.id = 0x36; break; - case Key::period: keyAddress.id = 0x37; break; - case Key::slash: keyAddress.id = 0x38; break; - case Key::caps_lock: keyAddress.id = 0x39; break; - case Key::f1: keyAddress.id = 0x3a; break; - case Key::f2: keyAddress.id = 0x3b; break; - case Key::f3: keyAddress.id = 0x3c; break; - case Key::f4: keyAddress.id = 0x3d; break; - case Key::f5: keyAddress.id = 0x3e; break; - case Key::f6: keyAddress.id = 0x3f; break; - case Key::f7: keyAddress.id = 0x40; break; - case Key::f8: keyAddress.id = 0x41; break; - case Key::f9: keyAddress.id = 0x42; break; - case Key::f10: keyAddress.id = 0x43; break; - case Key::f11: keyAddress.id = 0x44; break; - case Key::f12: keyAddress.id = 0x45; break; - case Key::print_screen: keyAddress.id = 0x46; break; - case Key::scroll_lock: keyAddress.id = 0x47; break; - case Key::pause_break: keyAddress.id = 0x48; break; - case Key::insert: keyAddress.id = 0x49; break; - case Key::home: keyAddress.id = 0x4a; break; - case Key::page_up: keyAddress.id = 0x4b; break; - case Key::del: keyAddress.id = 0x4c; break; - case Key::end: keyAddress.id = 0x4d; break; - case Key::page_down: keyAddress.id = 0x4e; break; - case Key::arrow_right: keyAddress.id = 0x4f; break; - case Key::arrow_left: keyAddress.id = 0x50; break; - case Key::arrow_bottom: keyAddress.id = 0x51; break; - case Key::arrow_top: keyAddress.id = 0x52; break; - case Key::num_lock: keyAddress.id = 0x53; break; - case Key::num_slash: keyAddress.id = 0x54; break; - case Key::num_asterisk: keyAddress.id = 0x55; break; - case Key::num_minus: keyAddress.id = 0x56; break; - case Key::num_plus: keyAddress.id = 0x57; break; - case Key::num_enter: keyAddress.id = 0x58; break; - case Key::num_1: keyAddress.id = 0x59; break; - case Key::num_2: keyAddress.id = 0x5a; break; - case Key::num_3: keyAddress.id = 0x5b; break; - case Key::num_4: keyAddress.id = 0x5c; break; - case Key::num_5: keyAddress.id = 0x5d; break; - case Key::num_6: keyAddress.id = 0x5e; break; - case Key::num_7: keyAddress.id = 0x5f; break; - case Key::num_8: keyAddress.id = 0x60; break; - case Key::num_9: keyAddress.id = 0x61; break; - case Key::num_0: keyAddress.id = 0x62; break; - case Key::num_dot: keyAddress.id = 0x63; break; - case Key::intl_backslash: keyAddress.id = 0x64; break; - case Key::menu: keyAddress.id = 0x65; break; - case Key::ctrl_left: keyAddress.id = 0xe0; break; - case Key::shift_left: keyAddress.id = 0xe1; break; - case Key::alt_left: keyAddress.id = 0xe2; break; - case Key::win_left: keyAddress.id = 0xe3; break; - case Key::ctrl_right: keyAddress.id = 0xe4; break; - case Key::shift_right: keyAddress.id = 0xe5; break; - case Key::alt_right: keyAddress.id = 0xe6; break; - case Key::win_right: keyAddress.id = 0xe7; break; - default: break; - } break; } - return true; + + for (uint8_t i = 0; i < keyArray.size(); i++) keyValues.push_back({keyArray[i], color}); + + return setKeys(keyValues); } -bool Keyboard::parsePowerOnEffect(std::string effect, PowerOnEffect &powerOnEffect) { - if (effect == "rainbow") powerOnEffect = PowerOnEffect::rainbow; - else if (effect == "color") powerOnEffect = PowerOnEffect::color; - else return false; - return true; +bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { + KeyValueArray keyValues; + for (uint8_t i = 0; i < keyGroupLogo.size(); i++) keyValues.push_back({keyGroupLogo[i], color}); + for (uint8_t i = 0; i < keyGroupIndicators.size(); i++) keyValues.push_back({keyGroupIndicators[i], color}); + for (uint8_t i = 0; i < keyGroupMultimedia.size(); i++) keyValues.push_back({keyGroupMultimedia[i], color}); + for (uint8_t i = 0; i < keyGroupGKeys.size(); i++) keyValues.push_back({keyGroupGKeys[i], color}); + for (uint8_t i = 0; i < keyGroupFKeys.size(); i++) keyValues.push_back({keyGroupFKeys[i], color}); + for (uint8_t i = 0; i < keyGroupFunctions.size(); i++) keyValues.push_back({keyGroupFunctions[i], color}); + for (uint8_t i = 0; i < keyGroupArrows.size(); i++) keyValues.push_back({keyGroupArrows[i], color}); + for (uint8_t i = 0; i < keyGroupNumeric.size(); i++) keyValues.push_back({keyGroupNumeric[i], color}); + for (uint8_t i = 0; i < keyGroupModifiers.size(); i++) keyValues.push_back({keyGroupModifiers[i], color}); + for (uint8_t i = 0; i < keyGroupKeys.size(); i++) keyValues.push_back({keyGroupKeys[i], color}); + return setKeys(keyValues); } -bool Keyboard::parseKey(std::string key, KeyAddress &keyAddress) { - std::transform(key.begin(), key.end(), key.begin(), ::tolower); - Key parsedKey; - if (key == "logo") parsedKey = Key::logo; - else if (key == "logo2") parsedKey = Key::logo2; - else if (key == "back_light" || key == "backlight" || key == "light") parsedKey = Key::backlight; - else if (key == "game_mode" || key == "gamemode" || key == "game") parsedKey = Key::game; - else if (key == "caps_indicator" || key == "capsindicator" || key == "caps") parsedKey = Key::caps; - else if (key == "scroll_indicator" || key == "scrollindicator" || key == "scroll") parsedKey = Key::scroll; - else if (key == "num_indicator" || key == "numindicator" || key == "num") parsedKey = Key::num; - else if (key == "next") parsedKey = Key::next; - else if (key == "prev" || key == "previous") parsedKey = Key::prev; - else if (key == "stop") parsedKey = Key::stop; - else if (key == "play_pause" || key == "playpause" || key == "play") parsedKey = Key::play; - else if (key == "mute") parsedKey = Key::mute; - else if (key == "a") parsedKey = Key::a; - else if (key == "b") parsedKey = Key::b; - else if (key == "c") parsedKey = Key::c; - else if (key == "d") parsedKey = Key::d; - else if (key == "e") parsedKey = Key::e; - else if (key == "f") parsedKey = Key::f; - else if (key == "g") parsedKey = Key::g; - else if (key == "h") parsedKey = Key::h; - else if (key == "i") parsedKey = Key::i; - else if (key == "j") parsedKey = Key::j; - else if (key == "k") parsedKey = Key::k; - else if (key == "l") parsedKey = Key::l; - else if (key == "m") parsedKey = Key::m; - else if (key == "n") parsedKey = Key::n; - else if (key == "o") parsedKey = Key::o; - else if (key == "p") parsedKey = Key::p; - else if (key == "q") parsedKey = Key::q; - else if (key == "r") parsedKey = Key::r; - else if (key == "s") parsedKey = Key::s; - else if (key == "t") parsedKey = Key::t; - else if (key == "u") parsedKey = Key::u; - else if (key == "v") parsedKey = Key::v; - else if (key == "w") parsedKey = Key::w; - else if (key == "x") parsedKey = Key::x; - else if (key == "z") parsedKey = Key::z; - else if (key == "y") parsedKey = Key::y; - else if (key == "1" || key == "one") parsedKey = Key::n1; - else if (key == "2" || key == "two") parsedKey = Key::n2; - else if (key == "3" || key == "three") parsedKey = Key::n3; - else if (key == "4" || key == "four") parsedKey = Key::n4; - else if (key == "5" || key == "five") parsedKey = Key::n5; - else if (key == "6" || key == "six") parsedKey = Key::n6; - else if (key == "7" || key == "seven") parsedKey = Key::n7; - else if (key == "8" || key == "eight") parsedKey = Key::n8; - else if (key == "9" || key == "nine") parsedKey = Key::n9; - else if (key == "0" || key == "zero") parsedKey = Key::n0; - else if (key == "enter") parsedKey = Key::enter; - else if (key == "esc" || key == "escape") parsedKey = Key::esc; - else if (key == "back" || key == "backspace") parsedKey = Key::backspace; - else if (key == "tab") parsedKey = Key::tab; - else if (key == "space") parsedKey = Key::space; - else if (key == "tilde" || key == "~") parsedKey = Key::tilde; - else if (key == "minus" || key == "-") parsedKey = Key::minus; - else if (key == "equal" || key == "=") parsedKey = Key::equal; - else if (key == "open_bracket" || key == "[") parsedKey = Key::open_bracket; - else if (key == "close_bracket" || key == "]") parsedKey = Key::close_bracket; - else if (key == "backslash" || key == "\\") parsedKey = Key::backslash; - else if (key == "semicolon" || key == ";") parsedKey = Key::semicolon; - else if (key == "quote" || key == "\"") parsedKey = Key::quote; - else if (key == "dollar" || key == "$") parsedKey = Key::dollar; - else if (key == "comma" || key == ",") parsedKey = Key::comma; - else if (key == "period" || key == ".") parsedKey = Key::period; - else if (key == "slash" || key == "/") parsedKey = Key::slash; - else if (key == "caps_lock" || key == "capslock") parsedKey = Key::caps_lock; - else if (key == "f1") parsedKey = Key::f1; - else if (key == "f2") parsedKey = Key::f2; - else if (key == "f3") parsedKey = Key::f3; - else if (key == "f4") parsedKey = Key::f4; - else if (key == "f5") parsedKey = Key::f5; - else if (key == "f6") parsedKey = Key::f6; - else if (key == "f7") parsedKey = Key::f7; - else if (key == "f8") parsedKey = Key::f8; - else if (key == "f9") parsedKey = Key::f9; - else if (key == "f10") parsedKey = Key::f10; - else if (key == "f11") parsedKey = Key::f11; - else if (key == "f12") parsedKey = Key::f12; - else if (key == "print_screen" || key == "printscreen" || key == "printscr" || key == "print") parsedKey = Key::print_screen; - else if (key == "scroll_lock" || key == "scrolllock") parsedKey = Key::scroll_lock; - else if (key == "pause_break" || key == "pausebreak" || key == "pause" || key == "break") parsedKey = Key::pause_break; - else if (key == "insert" || key == "ins") parsedKey = Key::insert; - else if (key == "home") parsedKey = Key::home; - else if (key == "page_up" || key == "pageup") parsedKey = Key::page_up; - else if (key == "delete" || key == "del") parsedKey = Key::del; - else if (key == "end") parsedKey = Key::end; - else if (key == "page_down" || key == "pagedown") parsedKey = Key::page_down; - else if (key == "arrow_right" || key == "arrowright" || key == "right") parsedKey = Key::arrow_right; - else if (key == "arrow_left" || key == "arrowleft" || key == "left") parsedKey = Key::arrow_left; - else if (key == "arrow_bottom" || key == "arrowbottom" || key == "bottom") parsedKey = Key::arrow_bottom; - else if (key == "arrow_top" || key == "arrowtop" || key == "top") parsedKey = Key::arrow_top; - else if (key == "num_lock" || key == "numlock") parsedKey = Key::num_lock; - else if (key == "num/" || key == "num_slash" || key == "numslash") parsedKey = Key::num_slash; - else if (key == "num*" || key == "num_asterisk" || key == "numasterisk") parsedKey = Key::num_asterisk; - else if (key == "num-" || key == "num_minus" || key == "numminus") parsedKey = Key::num_minus; - else if (key == "num+" || key == "num_plus" || key == "numplus") parsedKey = Key::num_plus; - else if (key == "numenter") parsedKey = Key::num_enter; - else if (key == "num1") parsedKey = Key::num_1; - else if (key == "num2") parsedKey = Key::num_2; - else if (key == "num3") parsedKey = Key::num_3; - else if (key == "num4") parsedKey = Key::num_4; - else if (key == "num5") parsedKey = Key::num_5; - else if (key == "num6") parsedKey = Key::num_6; - else if (key == "num7") parsedKey = Key::num_7; - else if (key == "num8") parsedKey = Key::num_8; - else if (key == "num9") parsedKey = Key::num_9; - else if (key == "num0") parsedKey = Key::num_0; - else if (key == "num." || key == "num_period" || key == "numperiod") parsedKey = Key::num_dot; - else if (key == "intl_backslash" || key == "<") parsedKey = Key::intl_backslash; - else if (key == "menu") parsedKey = Key::menu; - else if (key == "ctrl_left" || key == "ctrlleft" || key == "ctrll") parsedKey = Key::ctrl_left; - else if (key == "shift_left" || key == "shiftleft" || key == "shiftl") parsedKey = Key::shift_left; - else if (key == "alt_left" || key == "altleft" || key == "altl") parsedKey = Key::alt_left; - else if (key == "win_left" || key == "winleft" || key == "winl") parsedKey = Key::win_left; - else if (key == "meta_left" || key == "metaleft" || key == "metal") parsedKey = Key::win_left; - else if (key == "ctrl_right" || key == "ctrlright" || key == "ctrlr") parsedKey = Key::ctrl_right; - else if (key == "shift_right" || key == "shiftright" || key == "shiftr") parsedKey = Key::shift_right; - else if (key == "alt_right" || key == "altright" || key == "altr" || key == "altgr") parsedKey = Key::alt_right; - else if (key == "win_right" || key == "winright" || key == "winr") parsedKey = Key::win_right; - else if (key == "meta_right" || key == "metaright" || key == "metar") parsedKey = Key::win_right; - else if (key == "g1") parsedKey = Key::g1; - else if (key == "g2") parsedKey = Key::g2; - else if (key == "g3") parsedKey = Key::g3; - else if (key == "g4") parsedKey = Key::g4; - else if (key == "g5") parsedKey = Key::g5; - else if (key == "g6") parsedKey = Key::g6; - else if (key == "g7") parsedKey = Key::g7; - else if (key == "g8") parsedKey = Key::g8; - else if (key == "g9") parsedKey = Key::g9; - else return false; - return getKeyAddress(parsedKey, keyAddress); + +bool LedKeyboard::setStartupMode(StartupMode startupMode) { + byte_buffer_t data; + switch (m_keyboardModel) { + case KeyboardModel::g410: + case KeyboardModel::g610: + case KeyboardModel::g810: + data = { 0x11, 0xff, 0x0d, 0x5a, 0x00, 0x01 }; + break; + case KeyboardModel::g910: + data = { 0x11, 0xff, 0x10, 0x5e, 0x00, 0x01 }; + break; + default: + return false; + } + data.push_back((unsigned char)startupMode); + data.resize(20, 0x00); + return sendDataInternal(data); } -bool Keyboard::parseKeyGroup(std::string key, KeyGroup &keyGroup) { - if (key == "logo") keyGroup = KeyGroup::logo; - else if (key == "indicators") keyGroup = KeyGroup::indicators; - else if (key == "multimedia") keyGroup = KeyGroup::multimedia; - else if (key == "fkeys") keyGroup = KeyGroup::fkeys; - else if (key == "modifiers") keyGroup = KeyGroup::modifiers; - else if (key == "arrows") keyGroup = KeyGroup::arrows; - else if (key == "numeric") keyGroup = KeyGroup::numeric; - else if (key == "functions") keyGroup = KeyGroup::functions; - else if (key == "keys") keyGroup = KeyGroup::keys; - else if (key == "gkeys") keyGroup = KeyGroup::gkeys; - else return false; - return true; + +bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color) { + byte_buffer_t data; + switch (effect) { + + case NativeEffect::color: + data = { 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x01, color.red, color.green, color.blue, 0x02 }; + break; + case NativeEffect::breathing: + data = { + 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x02, + color.red, color.green, color.blue, speed, + 0x10, 0x00, 0x64 + }; + break; + case NativeEffect::cycle: + data = { + 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, speed, 0x00, 0x00, 0x64 + }; + break; + case NativeEffect::hwave: + switch (part) { + case NativeEffectPart::logo: + setNativeEffect(NativeEffect::color, part, 0, Color({0x00, 0xff, 0xff})); + break; + default: + data = { + 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x64, speed + }; + break; + } + break; + case NativeEffect::vwave: + switch (part) { + case NativeEffectPart::logo: + setNativeEffect(NativeEffect::color, part, 0, Color({0x00, 0xff, 0xff})); + break; + default: + data = { + 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x02, 0x64, speed + }; + break; + } + break; + case NativeEffect::cwave: + switch (part) { + case NativeEffectPart::logo: + setNativeEffect(NativeEffect::color, part, 0, Color({0x00, 0xff, 0xff})); + break; + default: + data = { + 0x11, 0xff, 0x0d, 0x3c, (uint8_t)part, 0x04, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x03, 0x64, speed + }; + break; + } + break; + + default: + return false; + } + + data.resize(20, 0x00); + return sendDataInternal(data); } -bool Keyboard::parseColor(std::string color, KeyColors &colors) { - if (color.length() == 2) color = color + "0000"; // For G610 - if (color.length() != 6) return false; - colors.red = std::stoul("0x"+color.substr(0,2), nullptr, 16); - colors.green = std::stoul("0x"+color.substr(2,2), nullptr, 16); - colors.blue = std::stoul("0x"+color.substr(4,2), nullptr, 16); - return true; -} -bool Keyboard::parseSpeed(std::string speed, uint8_t &speedValue) { - if (speed.length() == 1) speed = speed + "0"; - if (speed.length() != 2) return false; - speedValue = std::stoul("0x"+speed, nullptr, 16); - return true; -} -bool Keyboard::sendDataInternal(unsigned char *data, uint16_t data_size) { - if (m_isAttached == false) return false; +bool LedKeyboard::sendDataInternal(const byte_buffer_t &data) { + if (! m_isOpen) return false; int r; - if (data_size > 20) r = libusb_control_transfer(dev_handle, 0x21, 0x09, 0x0212, 1, data, data_size, 2000); - else r = libusb_control_transfer(dev_handle, 0x21, 0x09, 0x0211, 1, data, data_size, 2000); + if (data.size() > 20) r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, 1, const_cast(data.data()), data.size(), 2000); + else r = libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, 1, const_cast(data.data()), data.size(), 2000); usleep(1000); if (r < 0) return false; unsigned char buffer[64]; int len = 0; - r = libusb_interrupt_transfer(dev_handle, 0x82, buffer, sizeof(buffer), &len, 1); + r = libusb_interrupt_transfer(m_hidHandle, 0x82, buffer, sizeof(buffer), &len, 1); return true; } -bool Keyboard::populateAddressGroupInternal(KeyAddressGroup addressGroup, unsigned char *data) { - switch (kbdProtocol) { - case KeyboardProtocol::generic: - switch (addressGroup) { - case KeyAddressGroup::logo: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0c; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x10; // Base address - data[6] = 0x00; // Base address - data[7] = 0x01; // Base address - break; - case KeyAddressGroup::indicators: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0c; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x40; // Base address - data[6] = 0x00; // Base address - data[7] = 0x05; // Base address - break; - case KeyAddressGroup::multimedia: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0c; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x02; // Base address - data[6] = 0x00; // Base address - data[7] = 0x05; // Base address - break; - case KeyAddressGroup::keys: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0c; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x01; // Base address - data[6] = 0x00; // Base address - data[7] = 0x0e; // Base address - break; - default: - return false; - break; +LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddressGroup keyAddressGroup) { + switch (m_keyboardModel) { + case KeyboardModel::g410: + case KeyboardModel::g610: + case KeyboardModel::g810: + switch (keyAddressGroup) { + case LedKeyboard::KeyAddressGroup::logo: + return { 0x11, 0xff, 0x0c, 0x3a, 0x00, 0x10, 0x00, 0x01 }; + case LedKeyboard::KeyAddressGroup::indicators: + return { 0x12, 0xff, 0x0c, 0x3a, 0x00, 0x40, 0x00, 0x05 }; + case LedKeyboard::KeyAddressGroup::gkeys: + return {}; + case LedKeyboard::KeyAddressGroup::multimedia: + return { 0x12, 0xff, 0x0c, 0x3a, 0x00, 0x02, 0x00, 0x05 }; + case LedKeyboard::KeyAddressGroup::keys: + return { 0x12, 0xff, 0x0c, 0x3a, 0x00, 0x01, 0x00, 0x0e }; } break; - case KeyboardProtocol::g910: // gkeys and mkeys seem not changeable - switch (addressGroup) { - case KeyAddressGroup::logo: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0f; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x10; // Base address - data[6] = 0x00; // Base address - data[7] = 0x02; // Base address - break; - case KeyAddressGroup::indicators: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0c; // Base address - data[3] = 0x3a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x40; // Base address - data[6] = 0x00; // Base address - data[7] = 0x05; // Base address - break; - case KeyAddressGroup::keys: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0f; // Base address - data[3] = 0x3d; // Base address - data[4] = 0x00; // Base address - data[5] = 0x01; // Base address - data[6] = 0x00; // Base address - data[7] = 0x0e; // Base address - break; - case KeyAddressGroup::gkeys: - data[0] = 0x12; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0f; // Base address - data[3] = 0x3e; // Base address - data[4] = 0x00; // Base address - data[5] = 0x04; // Base address - data[6] = 0x00; // Base address - data[7] = 0x09; // Base address - break; - default: - return false; - break; + case KeyboardModel::g910: + switch (keyAddressGroup) { + case LedKeyboard::KeyAddressGroup::logo: + return { 0x11, 0xff, 0x0f, 0x3a, 0x00, 0x10, 0x00, 0x02 }; + case LedKeyboard::KeyAddressGroup::indicators: + return { 0x12, 0xff, 0x0c, 0x3a, 0x00, 0x40, 0x00, 0x05 }; + case LedKeyboard::KeyAddressGroup::gkeys: + return { 0x12, 0xff, 0x0f, 0x3e, 0x00, 0x04, 0x00, 0x09 }; + case LedKeyboard::KeyAddressGroup::multimedia: + return {}; + case LedKeyboard::KeyAddressGroup::keys: + return { 0x12, 0xff, 0x0f, 0x3d, 0x00, 0x01, 0x00, 0x0e }; } break; default: - return false; break; } - return true; -} - -bool Keyboard::populateFXAddressInternal(unsigned char *data) { - switch (kbdProtocol) { - case KeyboardProtocol::generic: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0d; // Base address - data[3] = 0x3c; // Base address - break; - case KeyboardProtocol::g910: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x10; // Base address - data[3] = 0x3c; // Base address - break; - default: - return false; - break; - } - return true; -} - -bool Keyboard::setKeysInternal(KeyAddressGroup addressGroup, KeyValue keyValues[], size_t keyValueCount) { - bool retval = false; - int data_size; - if (addressGroup == KeyAddressGroup::logo) data_size = 20; - else data_size = 64; - unsigned char *data = new unsigned char[data_size]; - const size_t maxKeyValueCount = (data_size - 8) / 4; - populateAddressGroupInternal(addressGroup, data); - for(size_t i = 0; i < maxKeyValueCount; i++) { - if (i < keyValueCount) { - data[8 + i * 4 + 0] = keyValues[i].key.id; - data[8 + i * 4 + 1] = keyValues[i].colors.red; - data[8 + i * 4 + 2] = keyValues[i].colors.green; - data[8 + i * 4 + 3] = keyValues[i].colors.blue; - } else { - data[8 + i * 4 + 0] = 0x00; - data[8 + i * 4 + 1] = 0x00; - data[8 + i * 4 + 2] = 0x00; - data[8 + i * 4 + 3] = 0x00; - } - } - retval = sendDataInternal(data, data_size); - delete[] data; - return retval; -} - -bool Keyboard::setPowerOnEffect(PowerOnEffect powerOnEffect) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - switch (kbdProtocol) { - case KeyboardProtocol::generic: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x0d; // Base address - data[3] = 0x5a; // Base address - data[4] = 0x00; // Base address - data[5] = 0x01; // Base address - case KeyboardProtocol::g910: - data[0] = 0x11; // Base address - data[1] = 0xff; // Base address - data[2] = 0x10; // Base address - data[3] = 0x5e; // Base address - data[4] = 0x00; // Base address - data[5] = 0x01; // Base address - } - switch (powerOnEffect) { - case PowerOnEffect::rainbow: - data[6] = 0x01; - break; - case PowerOnEffect::color: - data[6] = 0x02; - break; - } - for(int i = 7; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - delete[] data; - return retval; -} - -bool Keyboard::setKey(KeyValue keyValue) { - bool retval = false; - unsigned char *data; - int data_size; - if (keyValue.key.addressGroup == KeyAddressGroup::logo) { - data_size = 20; - data = new unsigned char[data_size]; - populateAddressGroupInternal(keyValue.key.addressGroup, data); - } else { - data_size = 64; - data = new unsigned char[data_size]; - populateAddressGroupInternal(keyValue.key.addressGroup, data); - } - data[8] = keyValue.key.id; - data[9] = keyValue.colors.red; - data[10] = keyValue.colors.green; - data[11] = keyValue.colors.blue; - for(int i = 12; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - delete[] data; - return retval; -} - -bool Keyboard::setKey(Key key, KeyColors colors) { - KeyValue keyValue; - getKeyAddress(key, keyValue.key); - keyValue.colors = colors; - return setKey(keyValue); -} - -bool Keyboard::setKeys(KeyValue keyValue[], size_t keyValueCount) { - const size_t maxLogoKeys = 5; - const size_t maxIndicatorsKeys = 25; - const size_t maxMultimediaKeys = 25; - const size_t maxKeys = 200; - const size_t maxGKeys = 25; - size_t logoCount = 0; - size_t indicatorsCount = 0; - size_t multimediaCount = 0; - size_t keysCount = 0; - size_t gkeysCount = 0; - KeyValue logo[maxLogoKeys]; - KeyValue indicators[maxIndicatorsKeys]; - KeyValue multimedia[maxMultimediaKeys]; - KeyValue keys[maxKeys]; - KeyValue gkeys[maxGKeys]; - - for (size_t i = 0; i < keyValueCount; i++) { - if(keyValue[i].key.addressGroup == KeyAddressGroup::logo && logoCount <= maxLogoKeys) { - logo[logoCount] = keyValue[i]; - logoCount++; - } else if(keyValue[i].key.addressGroup == KeyAddressGroup::indicators && indicatorsCount <= maxIndicatorsKeys) { - indicators[indicatorsCount] = keyValue[i]; - indicatorsCount++; - } else if(keyValue[i].key.addressGroup == KeyAddressGroup::multimedia && multimediaCount <= maxMultimediaKeys) { - multimedia[multimediaCount] = keyValue[i]; - multimediaCount++; - } else if(keyValue[i].key.addressGroup == KeyAddressGroup::keys && keysCount <= maxKeys) { - keys[keysCount] = keyValue[i]; - keysCount++; - } else if(keyValue[i].key.addressGroup == KeyAddressGroup::gkeys && gkeysCount <= maxGKeys) { - gkeys[gkeysCount] = keyValue[i]; - gkeysCount++; - } - } - - if (logoCount > 0) setKeysInternal(KeyAddressGroup::logo, logo, logoCount); - - if (indicatorsCount > 0) setKeysInternal(KeyAddressGroup::indicators, indicators, indicatorsCount); - - if (multimediaCount > 0) setKeysInternal(KeyAddressGroup::multimedia, multimedia, multimediaCount); - - if (keysCount > 0) { - const size_t maxKeyValueCount = 14; - for (size_t i = 0; i < keysCount; i = i + maxKeyValueCount) { - KeyValue keysBlock[maxKeyValueCount]; - size_t keysBlockCount = 0; - for (size_t j = 0; j < maxKeyValueCount; j++) { - if((i + j) < keysCount ) { - keysBlock[j] = keys[i + j]; - keysBlockCount++; - } - } - setKeysInternal(KeyAddressGroup::keys, keysBlock, keysBlockCount); - } - } - - if (gkeysCount > 0) setKeysInternal(KeyAddressGroup::gkeys, gkeys, gkeysCount); - - return true; -} - -bool Keyboard::setAllKeys(KeyColors colors) { - KeyValue keyValues[127]; - for (int i = 0; i < 127; i++) { - getKeyAddress((Key)i, keyValues[i].key); - keyValues[i].colors = colors; - } - setKeys(keyValues, 127); - return true; -} - -bool Keyboard::setGroupKeys(KeyGroup keyGroup, KeyColors colors) { - KeyValue keyValues[54]; - int keyValuesCount = 0; - switch (keyGroup) { - case KeyGroup::logo: - for (int i = 0; i < 2; i++) { - getKeyAddress((Key)i, keyValues[i].key); - keyValues[i].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::indicators: - for (int i = 2; i < 7; i++) { - getKeyAddress((Key)i, keyValues[i - 2].key); - keyValues[i - 2].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::multimedia: - for (int i = 7; i < 12; i++) { - getKeyAddress((Key)i, keyValues[i - 7].key); - keyValues[i - 7].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::fkeys: - for (int i = 12; i < 24; i++) { - getKeyAddress((Key)i, keyValues[i - 12].key); - keyValues[i - 12].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::modifiers: - for (int i = 24; i < 33; i++) { - getKeyAddress((Key)i, keyValues[i - 24].key); - keyValues[i - 24].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::arrows: - for (int i = 33; i < 37; i++) { - getKeyAddress((Key)i, keyValues[i - 33].key); - keyValues[i - 33].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::numeric: - for (int i = 37; i < 54; i++) { - getKeyAddress((Key)i, keyValues[i - 37].key); - keyValues[i - 37].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::functions: - for (int i = 54; i < 64; i++) { - getKeyAddress((Key)i, keyValues[i - 54].key); - keyValues[i - 54].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::keys: - for (int i = 64; i < 118; i++) { - getKeyAddress((Key)i, keyValues[i - 64].key); - keyValues[i - 64].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - case KeyGroup::gkeys: - for (int i = 118; i < 127; i++) { - getKeyAddress((Key)i, keyValues[i - 118].key); - keyValues[i - 118].colors = colors; - keyValuesCount++; - } - setKeys(keyValues, keyValuesCount); - break; - } - return true; -} - -bool Keyboard::setFXColorKeys(KeyColors colors) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x01; // Effect - data[6] = colors.red; - data[7] = colors.green; - data[8] = colors.blue; - data[9] = 0x02; - for(int i = 10; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXColorLogo(KeyColors colors) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Logo - populateFXAddressInternal(data); - data[4] = 0x01; // Logo - data[5] = 0x01; // Effect - data[6] = colors.red; - data[7] = colors.green; - data[8] = colors.blue; - data[9] = 0x02; - for(int i = 10; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXBreathingKeys(KeyColors colors, uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x02; // Effect - data[6] = colors.red; - data[7] = colors.green; - data[8] = colors.blue; - data[9] = speed; // Speed - data[10] = 0x10; // ??? - data[11] = 0x00; - data[12] = 0x64; - for(int i = 13; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXBreathingLogo(KeyColors colors, uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Logo - populateFXAddressInternal(data); - data[4] = 0x01; // Logo - data[5] = 0x02; // Effect - data[6] = colors.red; - data[7] = colors.green; - data[8] = colors.blue; - data[9] = speed; // Speed - data[10] = 0x10; // ??? - data[11] = 0x00; - data[12] = 0x64; - for(int i = 13; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXColorCycleKeys(uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x03; // Effect - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - data[9] = 0x00; - data[10] = 0x00; - data[11] = speed; // Speed - data[12] = 0x00; // ??? - data[13] = 0x00; - data[14] = 0x64; - for(int i = 15; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXColorCycleLogo(uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Logo - populateFXAddressInternal(data); - data[4] = 0x01; // Logo - data[5] = 0x03; // Effect - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - data[9] = 0x00; - data[10] = 0x00; - data[11] = speed; // Speed - data[12] = 0x00; // ??? - data[13] = 0x00; - data[14] = 0x64; - for(int i = 15; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXHWaveKeys(uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x04; // Effect - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - data[9] = 0x00; - data[10] = 0x00; - data[11] = 0x00; - data[12] = 0x88; - data[13] = 0x01; - data[14] = 0x64; - data[15] = speed; // Speed - for(int i = 16; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXVWaveKeys(uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x04; // Effect - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - data[9] = 0x00; - data[10] = 0x00; - data[11] = 0x00; - data[12] = 0x88; - data[13] = 0x02; - data[14] = 0x64; - data[15] = speed; // Speed - for(int i = 16; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; -} - -bool Keyboard::setFXCWaveKeys(uint8_t speed) { - bool retval = false; - int data_size = 20; - unsigned char *data = new unsigned char[data_size]; - - // Keys - populateFXAddressInternal(data); - data[4] = 0x00; // Keys - data[5] = 0x04; // Effect - data[6] = 0x00; - data[7] = 0x00; - data[8] = 0x00; - data[9] = 0x00; - data[10] = 0x00; - data[11] = 0x00; - data[12] = 0x88; - data[13] = 0x03; - data[14] = 0x64; - data[15] = speed; // Speed - for(int i = 16; i < data_size; i++) data[i] = 0x00; - retval = sendDataInternal(data, data_size); - - delete[] data; - return retval; + return {}; } diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index 5571e4e..86864cc 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -1,81 +1,195 @@ -#ifndef DEF_KEYBOARD -#define DEF_KEYBOARD +#ifndef KEYBOARD_CLASS +#define KEYBOARD_CLASS #include -#include +#include -class Keyboard { +#include "libusb-1.0/libusb.h" + + +class LedKeyboard { + + private: + + const std::vector> SuportedKeyboards = { + { 0x46d, 0xc330, (u_int16_t)KeyboardModel::g410 }, + { 0x46d, 0xc333, (u_int16_t)KeyboardModel::g610 }, + { 0x46d, 0xc338, (u_int16_t)KeyboardModel::g610 }, + { 0x46d, 0xc331, (u_int16_t)KeyboardModel::g810 }, + { 0x46d, 0xc337, (u_int16_t)KeyboardModel::g810 }, + { 0x46d, 0xc32b, (u_int16_t)KeyboardModel::g910 }, + { 0x46d, 0xc335, (u_int16_t)KeyboardModel::g910 } + }; + + + enum class KeyAddressGroup : uint8_t { + logo = 0x00, + indicators, + multimedia, + gkeys, + keys + }; + + public: - enum class KeyboardProtocol { generic, g910 }; - enum class PowerOnEffect { rainbow, color }; - enum class KeyAddressGroup { logo, indicators, multimedia, keys, gkeys }; - enum class Key { // 127 items - logo, logo2, - caps, num, scroll, game, backlight, - mute, play, stop, prev, next, - f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, - shift_left, ctrl_left, win_left, alt_left, alt_right, win_right, ctrl_right, shift_right, menu, - arrow_top, arrow_left, arrow_bottom, arrow_right, - num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0, num_dot, num_enter, num_plus, num_minus, num_asterisk, num_slash, num_lock, - esc, scroll_lock, - insert, del, home, end, page_up, page_down, print_screen, pause_break, - n1, n2, n3, n4, n5, n6, n7, n8, n9, n0, - tab, caps_lock, space, backspace, enter, - a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, - tilde, minus, equal, - open_bracket, close_bracket, backslash, - semicolon, quote, dollar, - intl_backslash, comma, period, slash, - g1, g2, g3, g4, g5, g6, g7, g8, g9 + enum class KeyboardModel : uint8_t { + unknown = 0x00, + g410, + g610, + g810, + g910 + }; + enum class StartupMode : uint8_t { + wave = 0x01, + color + }; + enum class NativeEffect : uint8_t { + color = 0x01, + breathing, + cycle, + hwave, + vwave, + cwave + }; + enum class NativeEffectPart : uint8_t { + all = 0xff, + keys = 0x00, + logo + }; + enum class KeyGroup : uint8_t { + logo = 0x00, + indicators, + multimedia, + gkeys, + fkeys, + modifiers, + functions, + arrows, + numeric, + keys + }; + enum class Key : uint16_t { // 127 items + + logo = static_cast(KeyAddressGroup::logo) << 8 | 0x01, + logo2, + + backlight = static_cast(KeyAddressGroup::indicators) << 8| 0x01, + game, caps, scroll, num, + + next = static_cast(KeyAddressGroup::multimedia) << 8 | 0xb5, + prev, stop, + play = static_cast(KeyAddressGroup::multimedia) << 8 | 0xcd, + mute = static_cast(KeyAddressGroup::multimedia) << 8 | 0xe2, + + g1 = static_cast(KeyAddressGroup::gkeys) << 8 | 0x01, + g2, g3, g4, g5, g6, g7, g8, g9, + + a = static_cast(KeyAddressGroup::keys) << 8 | 0x04, + b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, + n1, n2, n3, n4, n5, n6, n7, n8, n9, n0, + enter, esc, backspace, tab, space, minus, equal, open_bracket, close_bracket, + backslash, dollar, semicolon, quote, tilde, comma, period, slash, caps_lock, + f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, + print_screen, scroll_lock, pause_break, insert, home, page_up, del, end, page_down, + arrow_right, arrow_left, arrow_bottom, arrow_top, num_lock, num_slash, num_asterisk, + num_minus, num_plus, num_enter, + num_1, num_2, num_3, num_4, num_5, num_6, num_7, num_8, num_9, num_0, + num_dot, intl_backslash, menu, + + ctrl_left = static_cast(KeyAddressGroup::keys) << 8 | 0xe0, + shift_left, alt_left, win_left, + ctrl_right, shift_right, alt_right, win_right + }; - enum class KeyGroup { logo, indicators, multimedia, fkeys, modifiers, arrows, numeric, functions, keys, gkeys}; - struct KeyColors { uint8_t red; uint8_t green; uint8_t blue; }; - struct KeyAddress { KeyAddressGroup addressGroup; uint8_t id; }; - struct KeyValue { KeyAddress key; KeyColors colors; }; - bool isAttached(); - bool attach(); - bool detach(); + struct Color { + uint8_t red; + uint8_t green; + uint8_t blue; + }; + struct KeyValue { + LedKeyboard::Key key; + LedKeyboard::Color color; + }; + + typedef std::vector KeyValueArray; + + + ~LedKeyboard(); + + + bool listKeyboards(); + + bool isOpen(); + bool open(); + bool close(); + + KeyboardModel getKeyboardModel(); + bool commit(); - bool getKeyAddress(Key key, KeyAddress &keyAddress); - bool parsePowerOnEffect(std::string effect, PowerOnEffect &powerOnEffect); - bool parseKey(std::string key, KeyAddress &keyAddress); - bool parseKeyGroup(std::string key, KeyGroup &keyGroup); - bool parseColor(std::string color, KeyColors &colors); - bool parseSpeed(std::string speed, uint8_t &speedValue); - bool setPowerOnEffect(PowerOnEffect powerOnEffect); + bool setKey(KeyValue keyValue); - bool setKey(Key key, KeyColors colors); - bool setKeys(KeyValue keyValue[], size_t keyValueCount); - bool setAllKeys(KeyColors colors); - bool setGroupKeys(KeyGroup keyGroup, KeyColors colors); - bool setFXColorKeys(KeyColors colors); - bool setFXColorLogo(KeyColors colors); - bool setFXBreathingKeys(KeyColors colors, uint8_t speed); - bool setFXBreathingLogo(KeyColors colors, uint8_t speed); - bool setFXColorCycleKeys(uint8_t speed); - bool setFXColorCycleLogo(uint8_t speed); - bool setFXHWaveKeys(uint8_t speed); - bool setFXVWaveKeys(uint8_t speed); - bool setFXCWaveKeys(uint8_t speed); + bool setKeys(KeyValueArray keyValues); + bool setGroupKeys(KeyGroup keyGroup, Color color); + bool setAllKeys(Color color); + + bool setStartupMode(StartupMode startupMode); + + bool setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color); + private: - bool m_isAttached = false; - bool m_isKernellDetached = false; - KeyboardProtocol kbdProtocol = KeyboardProtocol::generic; - libusb_device **devs; - libusb_device_handle *dev_handle; - libusb_context *ctx = NULL; + typedef std::vector byte_buffer_t; + typedef std::vector KeyArray; - bool populateAddressGroupInternal(KeyAddressGroup addressGroup, unsigned char *data); - bool populateFXAddressInternal(unsigned char *data); - bool sendDataInternal(unsigned char *data, uint16_t data_size); - bool setKeysInternal(KeyAddressGroup addressGroup, KeyValue keyValues[], size_t keyValueCount); + + const KeyArray keyGroupLogo = { Key::logo, Key::logo2 }; + const KeyArray keyGroupIndicators = { Key::caps, Key::num, Key::scroll, Key::game, Key::backlight }; + const KeyArray keyGroupMultimedia = { Key::next, Key::prev, Key::stop, Key::play, Key::mute }; + const KeyArray keyGroupGKeys = { Key::g1, Key::g2, Key::g3, Key::g4, Key::g5, Key::g6, Key::g7, Key::g8, Key::g9 }; + const KeyArray keyGroupFKeys = { + Key::f1, Key::f2, Key::f3, Key::f4, Key::f5, Key::f6, + Key::f7, Key::f8, Key::f9, Key::f10, Key::f11, Key::f12 + }; + const KeyArray keyGroupModifiers = { + Key::shift_left, Key::ctrl_left, Key::win_left, Key::alt_left, + Key::alt_right, Key::win_right, Key::ctrl_right, Key::shift_right, Key::menu }; + const KeyArray keyGroupFunctions = { + Key::esc, Key::print_screen, Key::scroll_lock, Key::pause_break, + Key::insert, Key::del, Key::home, Key::end, Key::page_up, Key::page_down + }; + const KeyArray keyGroupArrows = { Key::arrow_top, Key::arrow_left, Key::arrow_bottom, Key::arrow_right }; + const KeyArray keyGroupNumeric = { + Key::num_1, Key::num_2, Key::num_3, Key::num_4, Key::num_5, + Key::num_6, Key::num_7, Key::num_8, Key::num_9, Key::num_0, + Key::num_dot, Key::num_enter, Key::num_plus, Key::num_minus, + Key::num_asterisk, Key::num_slash, Key::num_lock + }; + const KeyArray keyGroupKeys = { + Key::a, Key::b, Key::c, Key::d, Key::e, Key::f, Key::g, Key::h, Key::i, Key::j, Key::k, Key::l, Key::m, + Key::n, Key::o, Key::p, Key::q, Key::r, Key::s, Key::t, Key::u, Key::v, Key::w, Key::x, Key::y, Key::z, + Key::n1, Key::n2, Key::n3, Key::n4, Key::n5, Key::n6, Key::n7, Key::n8, Key::n9, Key::n0, + Key::enter, Key::esc, Key::backspace, Key::tab, Key::space, Key::minus, Key::equal, + Key::open_bracket, Key::close_bracket, Key::backslash, Key::dollar, Key::semicolon, Key::quote, Key::tilde, + Key::comma, Key::period, Key::slash, Key::caps_lock, Key::intl_backslash + }; + + bool m_isOpen = false; + bool m_isKernellDetached = false; + uint16_t m_vendorID = 0; + uint16_t m_productID = 0; + KeyboardModel m_keyboardModel = KeyboardModel::unknown; + libusb_device_handle *m_hidHandle; + libusb_context *m_ctx = NULL; + + + bool sendDataInternal(const byte_buffer_t &data); + byte_buffer_t getKeyGroupAddress(KeyAddressGroup keyAddressGroup); }; diff --git a/src/helpers/help.cpp b/src/helpers/help.cpp new file mode 100644 index 0000000..3092f09 --- /dev/null +++ b/src/helpers/help.cpp @@ -0,0 +1,187 @@ +#include "help.h" + +#include +#include "utils.h" + + +using namespace std; + +namespace help { + + + void usage(char *arg0) { + string cmdName = utils::getCmdName(arg0); + cout< + +namespace help { + + void usage(char *arg0); + void keys(char *arg0); + void effects(char *arg0); + void samples(char *arg0); + +} + +#endif diff --git a/src/helpers/utils.cpp b/src/helpers/utils.cpp new file mode 100644 index 0000000..19ce07a --- /dev/null +++ b/src/helpers/utils.cpp @@ -0,0 +1,212 @@ +#include "utils.h" + +#include +#include + +#include "../classes/Keyboard.h" + + +namespace utils { + + std::string getCmdName(std::string cmd) { + return cmd.substr(cmd.find_last_of("/\\") + 1); + } + + + + bool parseStartupMode(std::string val, LedKeyboard::StartupMode &startupMode) { + if (val == "wave") startupMode = LedKeyboard::StartupMode::wave; + else if (val == "color") startupMode = LedKeyboard::StartupMode::color; + else return false; + return true; + } + + bool parseNativeEffect(std::string val, LedKeyboard::NativeEffect &nativeEffect) { + if (val == "color") nativeEffect = LedKeyboard::NativeEffect::color; + else if (val == "cycle") nativeEffect = LedKeyboard::NativeEffect::cycle; + else if (val == "breathing") nativeEffect = LedKeyboard::NativeEffect::breathing; + else if (val == "hwave") nativeEffect = LedKeyboard::NativeEffect::hwave; + else if (val == "vwave") nativeEffect = LedKeyboard::NativeEffect::vwave; + else if (val == "cwave") nativeEffect = LedKeyboard::NativeEffect::cwave; + else return false; + return true; + } + + bool parseNativeEffectPart(std::string val, LedKeyboard::NativeEffectPart &nativeEffectPart) { + if (val == "all") nativeEffectPart = LedKeyboard::NativeEffectPart::all; + else if (val == "keys") nativeEffectPart = LedKeyboard::NativeEffectPart::keys; + else if (val == "logo") nativeEffectPart = LedKeyboard::NativeEffectPart::logo; + else return false; + return true; + } + + bool parseKey(std::string val, LedKeyboard::Key &key) { + std::transform(val.begin(), val.end(), val.begin(), ::tolower); + if (val == "logo") key = LedKeyboard::Key::logo; + else if (val == "logo2") key = LedKeyboard::Key::logo2; + else if (val == "back_light" || val == "backlight" || val == "light") key = LedKeyboard::Key::backlight; + else if (val == "game_mode" || val == "gamemode" || val == "game") key = LedKeyboard::Key::game; + else if (val == "caps_indicator" || val == "capsindicator" || val == "caps") key = LedKeyboard::Key::caps; + else if (val == "scroll_indicator" || val == "scrollindicator" || val == "scroll") key = LedKeyboard::Key::scroll; + else if (val == "num_indicator" || val == "numindicator" || val == "num") key = LedKeyboard::Key::num; + else if (val == "next") key = LedKeyboard::Key::next; + else if (val == "prev" || val == "previous") key = LedKeyboard::Key::prev; + else if (val == "stop") key = LedKeyboard::Key::stop; + else if (val == "play_pause" || val == "playpause" || val == "play") key = LedKeyboard::Key::play; + else if (val == "mute") key = LedKeyboard::Key::mute; + else if (val == "a") key = LedKeyboard::Key::a; + else if (val == "b") key = LedKeyboard::Key::b; + else if (val == "c") key = LedKeyboard::Key::c; + else if (val == "d") key = LedKeyboard::Key::d; + else if (val == "e") key = LedKeyboard::Key::e; + else if (val == "f") key = LedKeyboard::Key::f; + else if (val == "g") key = LedKeyboard::Key::g; + else if (val == "h") key = LedKeyboard::Key::h; + else if (val == "i") key = LedKeyboard::Key::i; + else if (val == "j") key = LedKeyboard::Key::j; + else if (val == "k") key = LedKeyboard::Key::k; + else if (val == "l") key = LedKeyboard::Key::l; + else if (val == "m") key = LedKeyboard::Key::m; + else if (val == "n") key = LedKeyboard::Key::n; + else if (val == "o") key = LedKeyboard::Key::o; + else if (val == "p") key = LedKeyboard::Key::p; + else if (val == "q") key = LedKeyboard::Key::q; + else if (val == "r") key = LedKeyboard::Key::r; + else if (val == "s") key = LedKeyboard::Key::s; + else if (val == "t") key = LedKeyboard::Key::t; + else if (val == "u") key = LedKeyboard::Key::u; + else if (val == "v") key = LedKeyboard::Key::v; + else if (val == "w") key = LedKeyboard::Key::w; + else if (val == "x") key = LedKeyboard::Key::x; + else if (val == "z") key = LedKeyboard::Key::z; + else if (val == "y") key = LedKeyboard::Key::y; + else if (val == "1" || val == "one") key = LedKeyboard::Key::n1; + else if (val == "2" || val == "two") key = LedKeyboard::Key::n2; + else if (val == "3" || val == "three") key = LedKeyboard::Key::n3; + else if (val == "4" || val == "four") key = LedKeyboard::Key::n4; + else if (val == "5" || val == "five") key = LedKeyboard::Key::n5; + else if (val == "6" || val == "six") key = LedKeyboard::Key::n6; + else if (val == "7" || val == "seven") key = LedKeyboard::Key::n7; + else if (val == "8" || val == "eight") key = LedKeyboard::Key::n8; + else if (val == "9" || val == "nine") key = LedKeyboard::Key::n9; + else if (val == "0" || val == "zero") key = LedKeyboard::Key::n0; + else if (val == "enter") key = LedKeyboard::Key::enter; + else if (val == "esc" || val == "escape") key = LedKeyboard::Key::esc; + else if (val == "back" || val == "backspace") key = LedKeyboard::Key::backspace; + else if (val == "tab") key = LedKeyboard::Key::tab; + else if (val == "space") key = LedKeyboard::Key::space; + else if (val == "tilde" || val == "~") key = LedKeyboard::Key::tilde; + else if (val == "minus" || val == "-") key = LedKeyboard::Key::minus; + else if (val == "equal" || val == "=") key = LedKeyboard::Key::equal; + else if (val == "open_bracket" || val == "[") key = LedKeyboard::Key::open_bracket; + else if (val == "close_bracket" || val == "]") key = LedKeyboard::Key::close_bracket; + else if (val == "backslash" || val == "\\") key = LedKeyboard::Key::backslash; + else if (val == "semicolon" || val == ";") key = LedKeyboard::Key::semicolon; + else if (val == "quote" || val == "\"") key = LedKeyboard::Key::quote; + else if (val == "dollar" || val == "$") key = LedKeyboard::Key::dollar; + else if (val == "comma" || val == ",") key = LedKeyboard::Key::comma; + else if (val == "period" || val == ".") key = LedKeyboard::Key::period; + else if (val == "slash" || val == "/") key = LedKeyboard::Key::slash; + else if (val == "caps_lock" || val == "capslock") key = LedKeyboard::Key::caps_lock; + else if (val == "f1") key = LedKeyboard::Key::f1; + else if (val == "f2") key = LedKeyboard::Key::f2; + else if (val == "f3") key = LedKeyboard::Key::f3; + else if (val == "f4") key = LedKeyboard::Key::f4; + else if (val == "f5") key = LedKeyboard::Key::f5; + else if (val == "f6") key = LedKeyboard::Key::f6; + else if (val == "f7") key = LedKeyboard::Key::f7; + else if (val == "f8") key = LedKeyboard::Key::f8; + else if (val == "f9") key = LedKeyboard::Key::f9; + else if (val == "f10") key = LedKeyboard::Key::f10; + else if (val == "f11") key = LedKeyboard::Key::f11; + else if (val == "f12") key = LedKeyboard::Key::f12; + else if (val == "print_screen" || val == "printscreen" || val == "printscr" || val == "print") + key = LedKeyboard::Key::print_screen; + else if (val == "scroll_lock" || val == "scrolllock") key = LedKeyboard::Key::scroll_lock; + else if (val == "pause_break" || val == "pausebreak" || val == "pause" || val == "break") + key = LedKeyboard::Key::pause_break; + else if (val == "insert" || val == "ins") key = LedKeyboard::Key::insert; + else if (val == "home") key = LedKeyboard::Key::home; + else if (val == "page_up" || val == "pageup") key = LedKeyboard::Key::page_up; + else if (val == "delete" || val == "del") key = LedKeyboard::Key::del; + else if (val == "end") key = LedKeyboard::Key::end; + else if (val == "page_down" || val == "pagedown") key = LedKeyboard::Key::page_down; + else if (val == "arrow_right" || val == "arrowright" || val == "right") key = LedKeyboard::Key::arrow_right; + else if (val == "arrow_left" || val == "arrowleft" || val == "left") key = LedKeyboard::Key::arrow_left; + else if (val == "arrow_bottom" || val == "arrowbottom" || val == "bottom") key = LedKeyboard::Key::arrow_bottom; + else if (val == "arrow_top" || val == "arrowtop" || val == "top") key = LedKeyboard::Key::arrow_top; + else if (val == "num_lock" || val == "numlock") key = LedKeyboard::Key::num_lock; + else if (val == "num/" || val == "num_slash" || val == "numslash") key = LedKeyboard::Key::num_slash; + else if (val == "num*" || val == "num_asterisk" || val == "numasterisk") key = LedKeyboard::Key::num_asterisk; + else if (val == "num-" || val == "num_minus" || val == "numminus") key = LedKeyboard::Key::num_minus; + else if (val == "num+" || val == "num_plus" || val == "numplus") key = LedKeyboard::Key::num_plus; + else if (val == "numenter") key = LedKeyboard::Key::num_enter; + else if (val == "num1") key = LedKeyboard::Key::num_1; + else if (val == "num2") key = LedKeyboard::Key::num_2; + else if (val == "num3") key = LedKeyboard::Key::num_3; + else if (val == "num4") key = LedKeyboard::Key::num_4; + else if (val == "num5") key = LedKeyboard::Key::num_5; + else if (val == "num6") key = LedKeyboard::Key::num_6; + else if (val == "num7") key = LedKeyboard::Key::num_7; + else if (val == "num8") key = LedKeyboard::Key::num_8; + else if (val == "num9") key = LedKeyboard::Key::num_9; + else if (val == "num0") key = LedKeyboard::Key::num_0; + else if (val == "num." || val == "num_period" || val == "numperiod") key = LedKeyboard::Key::num_dot; + else if (val == "intl_backslash" || val == "<") key = LedKeyboard::Key::intl_backslash; + else if (val == "menu") key = LedKeyboard::Key::menu; + else if (val == "ctrl_left" || val == "ctrlleft" || val == "ctrll") key = LedKeyboard::Key::ctrl_left; + else if (val == "shift_left" || val == "shiftleft" || val == "shiftl") key = LedKeyboard::Key::shift_left; + else if (val == "alt_left" || val == "altleft" || val == "altl") key = LedKeyboard::Key::alt_left; + else if (val == "win_left" || val == "winleft" || val == "winl") key = LedKeyboard::Key::win_left; + else if (val == "meta_left" || val == "metaleft" || val == "metal") key = LedKeyboard::Key::win_left; + else if (val == "ctrl_right" || val == "ctrlright" || val == "ctrlr") key = LedKeyboard::Key::ctrl_right; + else if (val == "shift_right" || val == "shiftright" || val == "shiftr") key = LedKeyboard::Key::shift_right; + else if (val == "alt_right" || val == "altright" || val == "altr" || val == "altgr") + key = LedKeyboard::Key::alt_right; + else if (val == "win_right" || val == "winright" || val == "winr") key = LedKeyboard::Key::win_right; + else if (val == "meta_right" || val == "metaright" || val == "metar") key = LedKeyboard::Key::win_right; + else if (val == "g1") key = LedKeyboard::Key::g1; + else if (val == "g2") key = LedKeyboard::Key::g2; + else if (val == "g3") key = LedKeyboard::Key::g3; + else if (val == "g4") key = LedKeyboard::Key::g4; + else if (val == "g5") key = LedKeyboard::Key::g5; + else if (val == "g6") key = LedKeyboard::Key::g6; + else if (val == "g7") key = LedKeyboard::Key::g7; + else if (val == "g8") key = LedKeyboard::Key::g8; + else if (val == "g9") key = LedKeyboard::Key::g9; + else return false; + return true; + } + + bool parseKeyGroup(std::string val, LedKeyboard::KeyGroup &keyGroup) { + if (val == "logo") keyGroup = LedKeyboard::KeyGroup::logo; + else if (val == "indicators") keyGroup = LedKeyboard::KeyGroup::indicators; + else if (val == "multimedia") keyGroup = LedKeyboard::KeyGroup::multimedia; + else if (val == "fkeys") keyGroup = LedKeyboard::KeyGroup::fkeys; + else if (val == "modifiers") keyGroup = LedKeyboard::KeyGroup::modifiers; + else if (val == "arrows") keyGroup = LedKeyboard::KeyGroup::arrows; + else if (val == "numeric") keyGroup = LedKeyboard::KeyGroup::numeric; + else if (val == "functions") keyGroup = LedKeyboard::KeyGroup::functions; + else if (val == "keys") keyGroup = LedKeyboard::KeyGroup::keys; + else if (val == "gkeys") keyGroup = LedKeyboard::KeyGroup::gkeys; + else return false; + return true; + } + + bool parseColor(std::string val, LedKeyboard::Color &color) { + if (val.length() == 2) val = val + "0000"; // For G610 + if (val.length() != 6) return false; + color.red = std::stoul("0x"+val.substr(0,2), nullptr, 16); + color.green = std::stoul("0x"+val.substr(2,2), nullptr, 16); + color.blue = std::stoul("0x"+val.substr(4,2), nullptr, 16); + return true; + } + + bool parseSpeed(std::string val, uint8_t &speed) { + if (val.length() == 1) val = "0" + val; + if (val.length() != 2) return false; + speed = std::stoul("0x" + val, nullptr, 16); + return true; + } + +} diff --git a/src/helpers/utils.h b/src/helpers/utils.h new file mode 100644 index 0000000..1fb16f7 --- /dev/null +++ b/src/helpers/utils.h @@ -0,0 +1,21 @@ +#ifndef UTILS_HELPER +#define UTILS_HELPER + +#include +#include "../classes/Keyboard.h" + +namespace utils { + + std::string getCmdName(std::string cmd); + + bool parseStartupMode(std::string val, LedKeyboard::StartupMode &startupMode); + bool parseNativeEffect(std::string val, LedKeyboard::NativeEffect &nativeEffect); + bool parseNativeEffectPart(std::string val, LedKeyboard::NativeEffectPart &nativeEffectPart); + bool parseKey(std::string val, LedKeyboard::Key &key); + bool parseKeyGroup(std::string val, LedKeyboard::KeyGroup &keyGroup); + bool parseColor(std::string val, LedKeyboard::Color &color); + bool parseSpeed(std::string val, uint8_t &speed); + +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index 4c2c8ee..c33047f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,511 +1,228 @@ -#include -#include -#include -#include +#include #include +#include +#include + +#include "helpers/help.h" +#include "helpers/utils.h" #include "classes/Keyboard.h" -using namespace std; -string appname = "g810-led"; - -void usage() { - cout< var; - vector keys; - - lg_kbd.attach(); - - while (!is.eof()) { - getline(is, line); - - if (line.substr(0, 3) == "var") { - line = line.substr(4); - ind = line.find(" "); - var[line.substr(0, ind)] = line.substr(ind + 1, 6); - } else if (line.substr(0, 1) == "a") { - line = line.substr(2); - if (line.substr(0, 1) == "$") { - ind = line.find(" "); - line = var[line.substr(1, ind - 1)]; - } else line = line.substr(0, 6); - if (lg_kbd.parseColor(line, colors) == true) { - keys.clear(); - lg_kbd.setAllKeys(colors); - } else cout<<"Error on line "< vars; + LedKeyboard::KeyValueArray keys = {}; + int retval = 0; + while (!stream.eof()) { + getline(stream, line); + if (line.size() > 0 && line.substr(0, 1) != "#") { + std::vector args = {}; + while (line.size() > 0) { + uint32_t ind = line.find(" "); + std::string argValue = line.substr(0, ind); + if (argValue.substr(0, 1) == "$") argValue = vars[argValue.substr(1)]; + args.push_back(argValue); + if (line.substr(0, ind) == line) line.clear(); + else line = line.substr(ind + 1); + } + if (args[0] == "var" && args.size() > 2) { + vars[args[1]] = args[2]; + } else if (args[0] == "c") { + if (kbd.open()) { + if (keys.size() > 0) { + if (! kbd.setKeys(keys)) retval = 1; + keys.clear(); + } + if(! kbd.commit()) retval = 1; + } else retval = 1; + } else if (args[0] == "a" && args.size() > 1) { + if (setAllKeys(kbd, args[1], false) == 1) retval = 1; + } else if (args[0] == "g" && args.size() > 2) { + if (setGroupKeys(kbd, args[1], args[2], false) == 1) retval = 1; + } else if (args[0] == "k" && args.size() > 2) { + LedKeyboard::Key key; + LedKeyboard::Color color; + if (utils::parseKey(args[1], key)) + if (utils::parseColor(args[2], color)) + keys.push_back({ key, color }); + } 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) { + if (setFX(kbd, args[1], args[2], args[3]) == 1) retval = 1; + } + } + } + return retval; +} + +int loadProfile(LedKeyboard &kbd, char *arg2) { + std::ifstream file; + file.open(arg2); if (file.is_open()) { - int retval = parseProfile(file); + int retval = 0; + retval = parseProfile(kbd, file); file.close(); return retval; } return 1; } -int pipeProfile() { +int pipeProfile(LedKeyboard &kbd) { if (isatty(fileno(stdin))) return 1; - return parseProfile(cin); + return parseProfile(kbd, std::cin); } -int main(int argc, char *argv[]) { - string str = argv[0]; - size_t split = str.find_last_of("/\\"); - str = str.substr(split + 1); - appname = str; + + +int main(int argc, char **argv) { + if (argc > 1) { - string argCmd = argv[1]; - if (argCmd == "-h" || argCmd == "--help") { usage(); return 0; } - else if (argCmd == "-lk" || argCmd == "--list-keys") { listkeys(); return 0; } - else if (argCmd == "-s" && argc == 3) return setStartupEffect(argv[2]); - else if (argCmd == "-a" && argc == 3) return setAllKeys(argv[2], true); - else if (argCmd == "-an" && argc == 3) return setAllKeys(argv[2], false); - else if (argCmd == "-g" && argc == 4) return setGroupKeys(argv[2], argv[3], true); - else if (argCmd == "-gn" && argc == 4) return setGroupKeys(argv[2], argv[3], false); - else if (argCmd == "-k" && argc == 4) return setKey(argv[2], argv[3], true); - else if (argCmd == "-kn" && argc == 4) return setKey(argv[2], argv[3], false); - else if (argCmd == "-c" && argc == 2) return commit(); - else if (argCmd == "-p" && argc == 3) return loadProfile(argv[2]); - else if (argCmd == "-pp" && argc == 2) return pipeProfile(); - else if (argCmd == "-fx-color" && argc == 3) return setFXColor(argv[2], true, true); - else if (argCmd == "-fx-breathing" && argc == 4) return setFXBreathing(argv[2], argv[3], true, true); - else if (argCmd == "-fx-cycle" && argc == 3) return setFXColorCycle(argv[2], true, true); - else if (argCmd == "-fx-hwave" && argc == 3) return setFXHWave(argv[2], true, true); - else if (argCmd == "-fx-vwave" && argc == 3) return setFXVWave(argv[2], true, true); - else if (argCmd == "-fx-cwave" && argc == 3) return setFXCWave(argv[2], true, true); - else if (argCmd == "-fxk-color" && argc == 3) return setFXColor(argv[2], true, false); - else if (argCmd == "-fxk-breathing" && argc == 4) return setFXBreathing(argv[2], argv[3], true, false); - else if (argCmd == "-fxk-cycle" && argc == 3) return setFXColorCycle(argv[2], true, false); - else if (argCmd == "-fxk-hwave" && argc == 3) return setFXHWave(argv[2], true, false); - else if (argCmd == "-fxk-vwave" && argc == 3) return setFXVWave(argv[2], true, false); - else if (argCmd == "-fxk-cwave" && argc == 3) return setFXCWave(argv[2], true, false); - else if (argCmd == "-fxl-color" && argc == 3) return setFXColor(argv[2], false, true); - else if (argCmd == "-fxl-breathing" && argc == 4) return setFXBreathing(argv[2], argv[3], false, true); - else if (argCmd == "-fxl-cycle" && argc == 3) return setFXColorCycle(argv[2], false, true); + + std::string arg = argv[1]; + + if (arg == "--help" || arg == "-h") help::usage(argv[0]); + else if (arg == "--help-keys") help::keys(argv[0]); + else if (arg == "--help-effects") help::effects(argv[0]); + else if (arg == "--help-samples") help::samples(argv[0]); + + else { + LedKeyboard kbd; + if (arg == "--list-keyboards") kbd.listKeyboards(); + else if (arg == "-c") return commit(kbd); + + else if (argc > 2 && arg == "-a") return setAllKeys(kbd, argv[2]); + else if (argc > 3 && arg == "-g") return setGroupKeys(kbd, argv[2], argv[3]); + else if (argc > 3 && arg == "-k") return setKey(kbd, argv[2], argv[3]); + else if (argc > 2 && arg == "-an") return setAllKeys(kbd, argv[2], false); + else if (argc > 3 && arg == "-gn") return setGroupKeys(kbd, argv[2], argv[3], false); + else if (argc > 3 && arg == "-kn") return setKey(kbd, argv[2], argv[3], false); + + else if (argc > 2 && arg == "-p") return loadProfile(kbd, argv[2]); + else if (argc > 1 && arg == "-pp") return pipeProfile(kbd); + + else if (argc > 5 && arg == "-fx") return setFX(kbd, argv[2], argv[3], argv[4], argv[5]); + else if (argc > 4 && arg == "-fx") return setFX(kbd, argv[2], argv[3], argv[4]); + + else if (argc > 2 && arg == "--startup-mode") return setStartupMode(kbd, argv[2]); + + else { help::usage(argv[0]); return 1; } + } + + return 0; + } - usage(); + + help::usage(argv[0]); return 1; }