commit fdc8220e70db692a40ae0fb5452bbed779ccef78 Author: MatMoul Date: Sun Jun 12 22:16:07 2016 +0200 First commit diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/README.md b/README.md new file mode 100644 index 0000000..819f944 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# g810-led + +Linux led controller for the Logitech G810 Keyboard + +(The old python project have moded to https://github.com/MatMoul/g810-led-python/) + +Dependencies :
+- lib-usb diff --git a/makefile b/makefile new file mode 100644 index 0000000..926cad7 --- /dev/null +++ b/makefile @@ -0,0 +1,15 @@ +CC=g++ +CFLAGS= +LDFLAGS=-lusb-1.0 + + +all: bin/g810-led + +bin/g810-led: src/main.cpp src/classes/* + $(CC) -o $@ $^ $(LDFLAGS) + +clean: + rm -rf *.o + +mrproper: clean + rm -rf $(EXEC) diff --git a/sample_profiles/all_blue b/sample_profiles/all_blue new file mode 100644 index 0000000..479f539 --- /dev/null +++ b/sample_profiles/all_blue @@ -0,0 +1,5 @@ +# Blue Profile + +a 0000ff # Set all keys blue + +c # Commit changes diff --git a/sample_profiles/all_green b/sample_profiles/all_green new file mode 100644 index 0000000..06a9993 --- /dev/null +++ b/sample_profiles/all_green @@ -0,0 +1,5 @@ +# Green Profile + +a 00ff00 # Set all keys green + +c # Commit changes diff --git a/sample_profiles/all_off b/sample_profiles/all_off new file mode 100644 index 0000000..b4e06a1 --- /dev/null +++ b/sample_profiles/all_off @@ -0,0 +1,5 @@ +# Off Profile + +a 000000 # Set all keys off + +c # Commit changes diff --git a/sample_profiles/all_red b/sample_profiles/all_red new file mode 100644 index 0000000..8d9d624 --- /dev/null +++ b/sample_profiles/all_red @@ -0,0 +1,5 @@ +# Red Profile + +a ff0000 # Set all keys red + +c # Commit changes diff --git a/sample_profiles/group_keys b/sample_profiles/group_keys new file mode 100644 index 0000000..98afb1a --- /dev/null +++ b/sample_profiles/group_keys @@ -0,0 +1,13 @@ +# Sample profile by groups keys + +g logo 000096 +g indicators 00ffff +g multimedia 009600 +g fkeys ff00ff +g modifiers ff0000 +g arrows ffff00 +g numeric 00ffff +g functions ffffff +g keys 009696 + +c # Commit changes diff --git a/sample_profiles/keys_v_gradiant b/sample_profiles/keys_v_gradiant new file mode 100644 index 0000000..89d16bb --- /dev/null +++ b/sample_profiles/keys_v_gradiant @@ -0,0 +1,129 @@ +# Sample profile vertical gradiant with vars and keys + +# Vars : +var raw0 00ffff +var raw1 960096 +var raw2 600096 +var raw3 300096 +var raw4 000096 +var raw5 003096 +var raw6 006096 + + +# Raw 0 : +g logo $raw0 +g indicators $raw0 +k mute $raw0 + +# Raw 1 : +k esc $raw1 +g fkeys $raw1 +k printscreen $raw1 +k scrolllock $raw1 +k pausebreak $raw1 +k play $raw1 +k stop $raw1 +k prev $raw1 +k next $raw1 + +# Raw 2 : +k ° $raw2 +k 1 $raw2 +k 2 $raw2 +k 3 $raw2 +k 4 $raw2 +k 5 $raw2 +k 6 $raw2 +k 7 $raw2 +k 8 $raw2 +k 9 $raw2 +k 0 $raw2 +k ? $raw2 +k tidle $raw2 +k backspace $raw2 +k insert $raw2 +k home $raw2 +k pageup $raw2 +k numlock $raw2 +k numslash $raw2 +k numasterisk $raw2 +k numminus $raw2 + +# Raw 3 : +k tab $raw3 +k q $raw3 +k w $raw3 +k e $raw3 +k r $raw3 +k t $raw3 +k z $raw3 +k u $raw3 +k i $raw3 +k o $raw3 +k p $raw3 +k è $raw3 +k ¨ $raw3 +k delete $raw3 +k end $raw3 +k pagedown $raw3 +k num7 $raw3 +k num8 $raw3 +k num9 $raw3 + +# Raw 4 : +k capslock $raw4 +k a $raw4 +k s $raw4 +k d $raw4 +k f $raw4 +k g $raw4 +k h $raw4 +k j $raw4 +k k $raw4 +k l $raw4 +k é $raw4 +k à $raw4 +k $ $raw4 +k enter $raw4 +k num4 $raw4 +k num5 $raw4 +k num6 $raw4 +k num+ $raw4 + +# Raw 5 : +k shiftl $raw5 +k < $raw5 +k y $raw5 +k x $raw5 +k c $raw5 +k v $raw5 +k b $raw5 +k n $raw5 +k m $raw5 +k , $raw5 +k . $raw5 +k - $raw5 +k shiftr $raw5 +k top $raw5 +k num1 $raw5 +k num2 $raw5 +k num3 $raw5 + +# Raw 6 : +k ctrll $raw6 +k winl $raw6 +k altl $raw6 +k space $raw6 +k altr $raw6 +k winr $raw6 +k menu $raw6 +k ctrlr $raw6 +k left $raw6 +k bottom $raw6 +k right $raw6 +k num0 $raw6 +k num. $raw6 +k numenter $raw6 + +# Commit +c diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp new file mode 100644 index 0000000..59821f6 --- /dev/null +++ b/src/classes/Keyboard.cpp @@ -0,0 +1,968 @@ +#include "Keyboard.h" +#include +#include +#include +#include +#include "/usr/include/libusb-1.0/libusb.h" + +using namespace std; + + +bool Keyboard::isAttached() { + return m_isAttached; +} + +bool Keyboard::attach() { + if (m_isAttached == true) return false; + int r; + r = libusb_init(&ctx); + if (r < 0) return false; + dev_handle = libusb_open_device_with_vid_pid(ctx, 0x046d, 0xc331); + if (dev_handle == NULL) { + libusb_exit(ctx); + ctx = NULL; + return false; + } + if(libusb_kernel_driver_active(dev_handle, 1) == 1) { + libusb_detach_kernel_driver(dev_handle, 1); + m_isKernellDetached = true; + } + r = libusb_claim_interface(dev_handle, 1); + if(r < 0) return false; + m_isAttached = true; + return true; +} + +bool Keyboard::detach() { + if (m_isAttached == false) return false; + int r; + r = libusb_release_interface(dev_handle, 1); + if(r!=0) return false; + if(m_isKernellDetached==true) { + libusb_attach_kernel_driver(dev_handle, 1); + m_isKernellDetached = false; + } + libusb_close(dev_handle); + dev_handle = NULL; + libusb_exit(ctx); + ctx = NULL; + m_isAttached = false; + return true; +} + +bool Keyboard::commit() { + if (m_isAttached == false) return false; + unsigned char *data = new unsigned char[20-1]; + data[0] = 0x11; + data[1] = 0xff; + data[2] = 0x0c; + data[3] = 0x5a; + return sendDataInternal(data, 20); +} + +bool Keyboard::getKeyAddress(Key key, KeyAddress &keyAddress) { + switch (key) { + case Key::logo: + keyAddress.addressGroup = KeyAddressGroup::logo; + keyAddress.id = 0x01; + break; + case Key::backlight: + keyAddress.addressGroup = KeyAddressGroup::indicators; + keyAddress.id = 0x01; + break; + case Key::game: + keyAddress.addressGroup = KeyAddressGroup::indicators; + keyAddress.id = 0x02; + break; + case Key::caps: + keyAddress.addressGroup = KeyAddressGroup::indicators; + keyAddress.id = 0x03; + break; + case Key::scroll: + keyAddress.addressGroup = KeyAddressGroup::indicators; + keyAddress.id = 0x04; + break; + case Key::num: + keyAddress.addressGroup = KeyAddressGroup::indicators; + keyAddress.id = 0x05; + break; + case Key::next: + keyAddress.addressGroup = KeyAddressGroup::multimedia; + keyAddress.id = 0xb5; + break; + case Key::prev: + keyAddress.addressGroup = KeyAddressGroup::multimedia; + keyAddress.id = 0xb6; + 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; + 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::z: keyAddress.id = 0x1c; break; + case Key::y: 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::apostrophe: keyAddress.id = 0x2d; break; // * + case Key::tidle: keyAddress.id = 0x2e; break; + case Key::open_bracket: keyAddress.id = 0x2f; break; + case Key::close_bracket: keyAddress.id = 0x30; break; + case Key::unknown: keyAddress.id = 0x31; break; // * + case Key::dollar: keyAddress.id = 0x32; break; // * + case Key::eaigu: keyAddress.id = 0x33; break; // * + case Key::agrave: keyAddress.id = 0x34; break; // * + case Key::degree: keyAddress.id = 0x35; break; // * + case Key::comma: keyAddress.id = 0x36; break; + case Key::dot: keyAddress.id = 0x37; break; + case Key::minus: 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::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; + } + break; + } + return true; +} + +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 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 == "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 == "'" || key == "?") parsedKey = Key::apostrophe; + else if (key == "tidle" || key == "^" || key == "~") parsedKey = Key::tidle; + else if (key == "open_bracket" || key == "openbracket" || key == "è" || key == "ü") parsedKey = Key::open_bracket; + else if (key == "close_bracket" || key == "closebracket" || key == "¨" || key == "!") parsedKey = Key::close_bracket; + else if (key == "unknown") parsedKey = Key::unknown; // Not on my keyboard + else if (key == "$" || key == "dollar") parsedKey = Key::dollar; + else if (key == "é" || key == "ö") parsedKey = Key::eaigu; + else if (key == "à" || key == "ä") parsedKey = Key::agrave; + else if (key == "§" || key == "°") parsedKey = Key::degree; + else if (key == "," || key == "comma") parsedKey = Key::comma; + else if (key == "." || key == "dot") parsedKey = Key::dot; + else if (key == "-" || key == "minus") parsedKey = Key::minus; + 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_dot" || key == "numdot") parsedKey = Key::num_dot; + else if (key == "<" || key == ">" || key == "\\" || key == "backslash") parsedKey = Key::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 return false; + return getKeyAddress(parsedKey, keyAddress); +} + +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 == "raw0") keyGroup = KeyGroup::raw0; + else if (key == "raw1") keyGroup = KeyGroup::raw1; + else if (key == "raw2") keyGroup = KeyGroup::raw2; + else if (key == "raw3") keyGroup = KeyGroup::raw3; + else if (key == "raw4") keyGroup = KeyGroup::raw4; + else if (key == "raw5") keyGroup = KeyGroup::raw5; + else if (key == "raw6") keyGroup = KeyGroup::raw6; + else return false; + return true; +} + +bool Keyboard::parseColor(std::string color, KeyColors &colors) { + 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; +} + +// TODO: Need work arround sleep and/or updatekeys ???? +bool Keyboard::sendDataInternal(unsigned char *data, int data_size) { + if (m_isAttached == false) return false; + int r; + r = libusb_control_transfer(dev_handle, 0x21, 0x09, 0x0211, 1, data, data_size, 0); + //sleep(0.01); + //sleep(0.5); + if (r < 0) return false; + return true; +} + +bool Keyboard::populateAddressGroupInternal(KeyAddressGroup addressGroup, unsigned char *data) { + 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; + } + return true; +} + +// TODO: Possible Bug +bool Keyboard::setKeysInternal(KeyAddressGroup addressGroup, KeyValue keyValues[], int keyValueCount) { + unsigned char *data; + int data_size; + if (addressGroup == KeyAddressGroup::logo) { + data_size = 20; + data = new unsigned char[data_size - 1]; + populateAddressGroupInternal(addressGroup, data); + data[8] = keyValues[0].key.id; + data[9] = keyValues[0].colors.red; + data[10] = keyValues[0].colors.green; + data[11] = keyValues[0].colors.blue; + for(int i = 12; i < data_size; i++) data[i] = 0x00; + } else { + data_size = 108; + data = new unsigned char[data_size - 1]; + populateAddressGroupInternal(addressGroup, data); + int maxKeyValueCount = (data_size - 8) / 4; + if (keyValueCount > maxKeyValueCount) keyValueCount = maxKeyValueCount; + for(int 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; + } + } + } + return sendDataInternal(data, data_size); +} + +bool Keyboard::setPowerOnEffect(PowerOnEffect powerOnEffect) { + int data_size = 20; + unsigned char *data = new unsigned char[data_size - 1]; + 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 + 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; + return sendDataInternal(data, data_size); +} + +bool Keyboard::setKey(KeyValue keyValue) { + unsigned char *data; + int data_size; + if (keyValue.key.addressGroup == KeyAddressGroup::logo) { + data_size = 20; + data = new unsigned char[data_size - 1]; + populateAddressGroupInternal(keyValue.key.addressGroup, data); + } else { + data_size = 108; + data = new unsigned char[data_size - 1]; + 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; + return sendDataInternal(data, data_size); +} + +bool Keyboard::setKey(Key key, KeyColors colors) { + KeyValue keyValue; + getKeyAddress(key, keyValue.key); + keyValue.colors = colors; + return setKey(keyValue); +} + +// TODO: maxKeyValueCount = 12 or 13, Why ? +bool Keyboard::setKeys(KeyValue keyValue[], int keyValueCount) { + KeyValue logo[5]; + int logoCount = 0; + KeyValue indicators[25]; + int indicatorsCount = 0; + KeyValue multimedia[25]; + int multimediaCount = 0; + KeyValue keys[200]; + int keysCount = 0; + + for (int i = 0; i < keyValueCount; i++) { + if(keyValue[i].key.addressGroup == KeyAddressGroup::logo) { + logo[logoCount] = keyValue[i]; + logoCount++; + } else if(keyValue[i].key.addressGroup == KeyAddressGroup::indicators) { + indicators[indicatorsCount] = keyValue[i]; + indicatorsCount++; + } else if(keyValue[i].key.addressGroup == KeyAddressGroup::multimedia) { + multimedia[multimediaCount] = keyValue[i]; + multimediaCount++; + } else if(keyValue[i].key.addressGroup == KeyAddressGroup::keys) { + keys[keysCount] = keyValue[i]; + keysCount++; + } + } + + if (logoCount > 0) setKey(logo[logoCount - 1]); + if (indicatorsCount > 0) { + for (int i = 0; i < indicatorsCount; i++) { + setKeysInternal(KeyAddressGroup::indicators, indicators, indicatorsCount); + commit(); + } + } + if (multimediaCount > 0) { + for (int i = 0; i < multimediaCount; i++) { + setKeysInternal(KeyAddressGroup::multimedia, multimedia, multimediaCount); + commit(); + } + } + if (keysCount > 0) { + int maxKeyValueCount = 2; + //int maxKeyValueCount = 4; + //int maxKeyValueCount = 10; + //int maxKeyValueCount = 12; + //int maxKeyValueCount = 13; + //int maxKeyValueCount = 14; Don't work + //int maxKeyValueCount = 20; + for (int i = 0; i < keysCount; i = i + maxKeyValueCount - 1) { + KeyValue keysBlock[maxKeyValueCount]; + int keysBlockCount = 0; + for (int j = 0; j < maxKeyValueCount; j++) { + keysBlock[j] = keys[i + j]; + keysBlockCount++; + } + setKeysInternal(KeyAddressGroup::keys, keysBlock, keysBlockCount); + commit(); + } + } + + return true; +} + +bool Keyboard::setAllKeys(KeyColors colors) { + KeyValue keyValues[118]; + for (int i = 0; i < 118; i++) { + getKeyAddress((Key)i, keyValues[i].key); + keyValues[i].colors = colors; + } + setKeys(keyValues, 118); + return true; +} + +bool Keyboard::setGroupKeys(KeyGroup keyGroup, KeyColors colors) { + KeyValue keyValues[118]; + int keyValuesCount = 0; + switch (keyGroup) { + case KeyGroup::logo: + setKey(Key::logo, colors); + break; + case KeyGroup::indicators: + for (int i = 1; i < 6; i++) { + getKeyAddress((Key)i, keyValues[i - 1].key); + keyValues[i - 1].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::multimedia: + for (int i = 6; i < 11; i++) { + getKeyAddress((Key)i, keyValues[i - 6].key); + keyValues[i - 6].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::fkeys: + for (int i = 11; i < 23; i++) { + getKeyAddress((Key)i, keyValues[i - 11].key); + keyValues[i - 11].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::modifiers: + for (int i = 23; i < 32; i++) { + getKeyAddress((Key)i, keyValues[i - 23].key); + keyValues[i - 23].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::arrows: + for (int i = 32; i < 36; i++) { + getKeyAddress((Key)i, keyValues[i - 32].key); + keyValues[i - 32].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::numeric: + for (int i = 36; i < 53; i++) { + getKeyAddress((Key)i, keyValues[i - 36].key); + keyValues[i - 36].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::functions: + for (int i = 53; i < 63; i++) { + getKeyAddress((Key)i, keyValues[i - 53].key); + keyValues[i - 53].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::keys: + for (int i = 63; i < 118; i++) { + getKeyAddress((Key)i, keyValues[i - 63].key); + keyValues[i - 63].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw0: + for (int i = 0; i < 6; i++) { + getKeyAddress((Key)i, keyValues[i].key); + keyValues[i].colors = colors; + keyValuesCount++; + } + getKeyAddress(Key::mute, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw1: + getKeyAddress(Key::esc, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + for (int i = 11; i < 23; i++) { + getKeyAddress((Key)i, keyValues[i - 11 + 1].key); + keyValues[i - 11 + 1].colors = colors; + keyValuesCount++; + } + getKeyAddress(Key::print_screen, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::scroll_lock, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::pause_break, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + for (int i = 7; i < 11; i++) { + getKeyAddress((Key)i, keyValues[i - 7 + 16].key); + keyValues[i - 7 + 16].colors = colors; + keyValuesCount++; + } + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw2: + getKeyAddress(Key::degree, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + for (int i = 63; i < 73; i++) { + getKeyAddress((Key)i, keyValues[i - 63 + 1].key); + keyValues[i - 63 + 1].colors = colors; + keyValuesCount++; + } + getKeyAddress(Key::apostrophe, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::tidle, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::backspace, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::insert, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::home, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::page_up, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_lock, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_slash, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_asterisk, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_minus, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw3: + getKeyAddress(Key::tab, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::q, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::w, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::e, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::r, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::t, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::z, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::u, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::i, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::o, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::p, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::open_bracket, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::close_bracket, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::del, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::end, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::page_down, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_7, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_8, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_9, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw4: + getKeyAddress(Key::caps_lock, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::a, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::s, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::d, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::f, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::g, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::h, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::j, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::k, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::l, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::eaigu, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::agrave, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::dollar, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::enter, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_4, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_5, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_6, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_plus, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw5: + getKeyAddress(Key::shift_left, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::backslash, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::y, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::x, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::c, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::v, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::b, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::n, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::m, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::comma, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::dot, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::minus, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::shift_right, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::arrow_top, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_1, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_2, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_3, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + case KeyGroup::raw6: + getKeyAddress(Key::ctrl_left, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::win_left, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::alt_left, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::space, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::alt_right, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::win_right, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::menu, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::ctrl_right, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::arrow_left, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::arrow_bottom, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::arrow_right, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_0, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_dot, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + getKeyAddress(Key::num_enter, keyValues[keyValuesCount].key); + keyValues[keyValuesCount].colors = colors; + keyValuesCount++; + setKeys(keyValues, keyValuesCount); + break; + } +} diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h new file mode 100644 index 0000000..c9f2d6d --- /dev/null +++ b/src/classes/Keyboard.h @@ -0,0 +1,66 @@ +#ifndef DEF_KEYBOARD +#define DEF_KEYBOARD + +#include +#include "/usr/include/libusb-1.0/libusb.h" + +class Keyboard { + + public: + + enum class PowerOnEffect { rainbow, color }; + enum class KeyAddressGroup { logo, indicators, multimedia, keys }; + enum class Key { // 118 items + logo, + 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, + unknown, egrave, eaigu, agrave, dollar, apostrophe, degree, backslash, // Need best names + comma, dot, minus, open_bracket, close_bracket, tidle + }; + enum class KeyGroup { logo, indicators, multimedia, fkeys, modifiers, arrows, numeric, functions, keys, raw0, raw1, raw2, raw3, raw4, raw5, raw6 }; + + struct KeyColors { char red; char green; char blue; }; + struct KeyAddress { KeyAddressGroup addressGroup; char id; }; + struct KeyValue { KeyAddress key; KeyColors colors; }; + + bool isAttached(); + bool attach(); + bool detach(); + 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 setPowerOnEffect(PowerOnEffect powerOnEffect); + bool setKey(KeyValue keyValue); + bool setKey(Key key, KeyColors colors); + bool setKeys(KeyValue keyValue[], int keyValueCount); + bool setAllKeys(KeyColors colors); + bool setGroupKeys(KeyGroup keyGroup, KeyColors colors); + + + private: + + bool m_isAttached = false; + bool m_isKernellDetached = false; + libusb_device **devs; + libusb_device_handle *dev_handle; + libusb_context *ctx = NULL; + + bool populateAddressGroupInternal(KeyAddressGroup addressGroup, unsigned char *data); + bool sendDataInternal(unsigned char *data, int data_size); + bool setKeysInternal(KeyAddressGroup addressGroup, KeyValue keyValues[], int keyValueCount); + +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..2e45feb --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,225 @@ +//#include +#include +#include +#include +#include +#include +#include +#include "classes/Keyboard.h" + +using namespace std; + + +void usage() { + cout<<"g810-led Usages :\n"; + cout<<"-----------------\n"; + cout<<"\n"; + cout<<" -s effect :\t\tSet keyboard startup effect\n"; + cout<<"\n"; + cout<<" -a color :\t\tSet all keys\n"; + cout<<" -g group, color :\tSet a group of keys\n"; + cout<<" -k key, color :\tSet a key\n"; + cout<<"\n"; + cout<<" -an color :\t\tSet all keys without commit\n"; + cout<<" -gn group, color :\tSet a group of keys without commit\n"; + cout<<" -kn key, color :\tSet a key without commit\n"; + cout<<"\n"; + cout<<" -c :\t\t\tCommit changes\n"; + cout<<"\n"; + cout<<" -p porfilefile :\tLoad a profile\n"; + cout<<"\n"; + cout<<" -h | --help :\t\tthis help message\n"; + cout<<"\n"; + cout<<"color formats :\t\tRRGGBB (hex value for red, green and blue)\n"; + cout<<"\n"; + cout<<"effect values :\t\trainbow, color\n"; + cout<<"key values :\t\tabc... 123... and other\n"; + cout<<"group values :\t\tlogo, indicators, fkeys, modifiers, multimedia, arrows, numeric, functions, keys\n"; + cout<<"\t\t\traw0, raw1, raw2, raw3, raw4, raw5, raw6\n"; + cout<<"\n"; + cout<<"sample :\n"; + cout<<"g810-led -k logo ff0000\n"; + cout<<"g810-led -a 00ff00\n"; + cout<<"g810-led -g fkeys ff00ff\n"; + cout<<"g810-led -s color\n"; +} + +int commit() { + Keyboard g810; + g810.attach(); + g810.commit(); + g810.detach(); + return 0; +} + +int setStartupEffect(string effect) { + Keyboard g810; + Keyboard::PowerOnEffect powerOnEffect; + if (g810.parsePowerOnEffect(effect, powerOnEffect) == true) { + g810.attach(); + g810.setPowerOnEffect(powerOnEffect); + g810.commit(); + g810.detach(); + return 0; + } + return 1; +} + +int setKey(string key, string color, bool commit) { + Keyboard g810; + Keyboard::KeyAddress keyAddress; + if (g810.parseKey(key, keyAddress) == true) { + Keyboard::KeyColors colors; + if (g810.parseColor(color, colors) == true) { + Keyboard::KeyValue keyValue; + keyValue.key = keyAddress; + keyValue.colors = colors; + g810.attach(); + g810.setKey(keyValue); + if (commit == true) g810.commit(); + g810.detach(); + return 0; + } + } + return 1; +} + +int setAllKeys(string color, bool commit) { + Keyboard g810; + Keyboard::KeyColors colors; + if (g810.parseColor(color, colors) == true) { + g810.attach(); + g810.setAllKeys(colors); + if (commit == true) g810.commit(); + g810.detach(); + return 0; + } + return 1; +} + +int setGroupKeys(string groupKeys, string color, bool commit) { + Keyboard g810; + Keyboard::KeyGroup keyGroup; + if (g810.parseKeyGroup(groupKeys, keyGroup) == true) { + Keyboard::KeyColors colors; + if (g810.parseColor(color, colors) == true) { + g810.attach(); + g810.setGroupKeys(keyGroup, colors); + if (commit == true) g810.commit(); + g810.detach(); + //delete [] g810; + return 0; + } + } + return 1; +} + +int loadProfile(string profileFile) { + ifstream file; + + file.open(profileFile); + if (file.is_open()) { + + string line; + int lineCount = 1; + int ind; + bool commit; + + Keyboard g810; + Keyboard::KeyGroup keyGroup; + Keyboard::KeyAddress keyAddress; + Keyboard::KeyValue keyValue; + Keyboard::KeyColors colors; + + map var; + vector keys; + + g810.attach(); + + while (!file.eof()) { + getline(file, 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 (g810.parseColor(line, colors) == true) { + keys.clear(); + g810.setAllKeys(colors); + } else cout<<"Error on line "< 1) { + string argCmd = argv[1]; + if (argCmd == "-h" || argCmd == "--help") { usage(); 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]); + } + usage(); + return 1; +} diff --git a/wireshark_dumps/set_boot_color.pcapng b/wireshark_dumps/set_boot_color.pcapng new file mode 100644 index 0000000..ca2d889 Binary files /dev/null and b/wireshark_dumps/set_boot_color.pcapng differ diff --git a/wireshark_dumps/set_boot_rainbow.pcapng b/wireshark_dumps/set_boot_rainbow.pcapng new file mode 100644 index 0000000..61e3c8e Binary files /dev/null and b/wireshark_dumps/set_boot_rainbow.pcapng differ diff --git a/wireshark_dumps/set_keys_colors.pcapng b/wireshark_dumps/set_keys_colors.pcapng new file mode 100644 index 0000000..ec4dceb Binary files /dev/null and b/wireshark_dumps/set_keys_colors.pcapng differ