diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c948f71 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin/* +lib/* +. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5ef5d45 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,19 @@ +# g810-led CONTRIBUTING + +## Share your profile or make dump : +* [https://github.com/MatMoul/g810-led-resources](https://github.com/MatMoul/g810-led-resources) + +## Contributing : +* Open an issue before work to hard +* Work on the develop branch + +## Tasks (Help wanted) : +* (0%) AVERAGE: Add selection of multiple keyboards by index +* (0%) AVERAGE: Improve INSTALL.md to support more distributions (And CentOS with hidapi) +* (10%) AVERAGE: Make distributions ready package +* (0%) IMAGINATION: Use a more generic name for project, config dir and systemd units ([issue 29](https://github.com/MatMoul/g810-led/issues/29)) + +## Possible enhancements : +* Add deamon mode for custom effects (Add G Keys handler [issue 39](https://github.com/MatMoul/g810-led/issues/39), [CReimer](https://github.com/CReimer/g910-gkey-uinput))) +* Support country based keybord ([issue 16](https://github.com/MatMoul/g810-led/issues/16) but very hard) +* Support of new G Mouse like the G403 ([issue 40](https://github.com/MatMoul/g810-led/issues/40)) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..93320bf --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,55 @@ +# g810-led - CONTRIBUTORS (alpha order) :
+ +## [andreast1990](https://github.com/andreast1990) : +* Add Wireshark dump for g910 + +## [barul42](https://github.com/barul42) : +* Improve INSTALL.MD + +## [carlba](https://github.com/carlba) : +* Improve install file + +## [CReimer](https://github.com/CReimer) : +* Add Wireshark dump for g910 M and G keys +* Debug hidapi missing keys on certain computer + +## [dkolosa](https://github.com/dkolosa) : +* Provide alternative productid for g910 + +## [francoisfreitag](https://github.com/francoisfreitag) : +* Refactor makefile (hard work) + +## [hschreck](https://github.com/hschreck) : +* Fix typo + +## [jdagerbo](https://github.com/jdagerbo) : +* Refactor many of the code (very hard work) + +## [Landrovan](https://github.com/Landrovan) : +* Improve support of G410 (two times) + +## [larsnaesbye](https://github.com/larsnaesbye) : +* Fix typo + +## [lynix](https://github.com/lynix) : +* Improve makefile + +## [matthunz](https://github.com/matthunz) : +* Improve INSTALL.MD for ArchLinux + +## [MohamadSaada](https://github.com/MohamadSaada) : +* Add poweron effect bytes for g910 +* Debug setKeys (hard work) + +## [noisycat](https://github.com/noisycat) : +* Add wireshark dump effects +* Improve makefile + +## [pearsonk](https://github.com/pearsonk) : +* Add g213 protocol (very hard work) +* Add support of g213 +* Implement underlying device IO as a shared library +* Add multiple keyboard support (very hard work) + +## [wextia](https://github.com/wextia) : +* Fixed incorrect markdown formatting in README.md diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..02c9786 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,59 @@ +# Installation :
+ +## Build dependencies :
+* git +* g++ +* make + +## Dependencies :
+* hidapi or libusb + +## hidapi vs libusb :
+hidapi is a newer implementation but needs more testing.
+hidapi is more responsive than libusb (~20ms vs ~150ms).
+hidapi seems to not work on CentOS, writing to hidraw is not allowed.
+hidapi is recommended but if you encounter a problem on your system, switch to libusb.
+ + +## Installation using repos :
+ArchLinux (aur) :
+`yaourt -S g810-led-git` # with yaourt
+`pacaur -S g810-led-git` # with pacaur
+ + +## Installation of dependencies :
+ArchLinux :
+`sudo pacman -S git gcc make hidapi` # for hidapi
+`sudo pacman -S git gcc make libusb` # for libusb
+Debian :
+`sudo apt-get install git g++ make libhidapi-dev` # for hidapi
+`sudo apt-get install git g++ make libusb-1.0-0-dev` # for libusb
+Fedora :
+`sudo dnf install git make gcc-c++ hidapi-devel` # for hidapi
+`sudo dnf install git make gcc-c++ libusbx-devel` # for libusb
+ +## Installation :
+`git clone https://github.com/MatMoul/g810-led.git`
+`cd g810-led`
+`make bin` # for hidapi
+`make bin LIB=libusb` # for libusb
+`sudo make install`
+ +## Installation of the library (For developers) :
+`make lib` # for hidapi
+`make lib LIB=libusb` # for libusb
+`sudo make install-lib` to install the libg810-led library.
+`sudo make install-dev` to install the libg810-led library and headers for development.
+ +## Update :
+Same as install, but your profile and reboot files are preserved.
+ +## Uninstall :
+`sudo make uninstall`
+ +## Boot profiles :
+On boot, the keyboard is set with the udev file /etc/udev/rules.d/g810-led.rules
+This file launches the profile stored in /etc/g810-led/profile
+To prevent your keyboard flashing 3 times when you reboot use the systemd unit (g810-led-reboot).
+ +Samples can be found in /etc/g810-led/samples.
diff --git a/README.md b/README.md index cf1e9e3..9d653d4 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,55 @@ -# g810-led +# g810-led
-Linux LED controller for the Logitech G810 Orion Spectrum Keyboard +Linux led controller for Logitech G213, G410, G413, G512, G513, G610, G810, G910 and GPRO Keyboards.
-Other compatible keyboard :
-G410 Atlas Spectrum
-G610 Orion
-G910 Orion Spark
-G910 Orion Spectrum +## Compatible keyboards :
+- **G213 Prodigy**
+- **G410 Atlas Spectrum**
+- **G413 Carbon**
+- **G512 Carbon**
+- **G513 Carbon**
+- **G610 Orion Brown**
+- **G610 Orion Red**
+- **G810 Orion Spectrum**
+- **G910 Orion Spark**
+- **G910 Orion Spectrum**
+- **GPRO**
-![jj](https://raw.githubusercontent.com/MatMoul/g810-led/master/pictures/logitech_g810-2.jpg) +## Contribute and evolution :
+* [CONTRIBUTING.md](https://github.com/MatMoul/g810-led/blob/master/CONTRIBUTING.md) -Install and use :
-- look at the wiki : https://github.com/MatMoul/g810-led/wiki +## Install :
+* [INSTALL.md](https://github.com/MatMoul/g810-led/blob/master/INSTALL.md) -Samples :
-`g810-led -p /etc/g810/profile # Set a profile`
+## Help :
+`g213-led --help`
+`g410-led --help`
+`g413-led --help`
+`g512-led --help`
+`g513-led --help`
+`g610-led --help`
+`g810-led --help`
+`g910-led --help`
+`gpro-led --help`
+ +`g810-led --help-keys`
+`g810-led --help-effects`
+`g810-led --help-samples`
+ +## Samples :
+`g810-led -p /etc/g810/profile # Load a profile`
`g810-led -k logo ff0000 # Set color of a key`
`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 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 :
+## Samples with no commit :
`g810-led -an 000000 # Set color of all key with no action`
`g810-led -gn modifiers ff0000 # Set color of a group with no action`
`g810-led -kn w ff0000 # Set color of a key with no action`
@@ -28,3 +57,43 @@ Samples with no commit :
`g810-led -kn s ff0000 # Set color of a key with no action`
`g810-led -kn d ff0000 # Set color of a key with no action`
`g810-led -c # Commit all changes`
+ +## Samples for G610 :
+`g610-led -a 60 # Set intensity of all keys`
+`g610-led -k logo ff # Set intensity of a key`
+`g610-led -g fkeys aa # Set intensity of a group of keys`
+ +## Samples for G213 :
+`g213-led -a 00ff00 # Set all keys green`
+`g213-led -r 1 ff0000 # Set region 1 red`
+ +## Samples with pipe (for effects) :
+`g810-led -pp < profilefile # Load a profile`
+`echo -e "k w ff0000\nk a ff0000\nk s ff0000\nk d ff0000\nc" | g810-led -pp # Set multiple keys`
+ +## Testing unsuported keyboards :
+Start by retrieving the VendorID and the ProductID of your keyboard using lsusb.
+`lsusb`
+Sample return :
+`Bus 001 Device 001: ID 046d:c331 Logitech, Inc.`
+In this sample VendorID is 046d and ProductID is c331. Now test your keyboard with all supported protocol :
+`g810-led -dv 046d -dp c331 -tuk 1 -a 000000`
+If your keyboard set all key to off you have found the protocol (1), if not continue.
+`g810-led -dv 046d -dp c331 -tuk 2 -a 000000`
+If your keyboard set all key to off you have found the protocol (2), if not continue.
+`g810-led -dv 046d -dp c331 -tuk 3 -a 000000`
+If your keyboard set all key to off you have found the protocol (3), if not, need new dump.
+ +## Building and linking against the libg810-led library :
+Include in implementing source files.
+```cpp +#include +``` +To link, simply provide `-lg810-led` to the build flags.
+ +To build the g810-led application as a dynamically-linked variant, run the target:
+`make bin-linked`
+ +## Dumps : +Dumps of keyboards are now stored in a separate project to preserve a small download size of this project. +You can find them here : [https://github.com/MatMoul/g810-led-resources](https://github.com/MatMoul/g810-led-resources) diff --git a/makefile b/makefile index 24826e8..3741c14 100644 --- a/makefile +++ b/makefile @@ -1,20 +1,120 @@ -CC=g++ -CFLAGS=-Wall -O2 -std=gnu++11 -LIBUSB_INC?=-I/usr/include/libusb-1.0 -LDFLAGS=-lusb-1.0 +CXX?=g++ +CXXFLAGS?=-Wall -O2 +LIB?=hidapi +ifeq ($(LIB),libusb) + CPPFLAGS=-Dlibusb + LIBS=-lusb-1.0 +else + CPPFLAGS=-Dhidapi + LIBS=-lhidapi-hidraw +endif +SYSTEMDDIR?=/usr/lib/systemd + +PREFIX?=$(DESTDIR)/usr +libdir?=$(PREFIX)/lib +includedir?=$(PREFIX)/include + +# Program & versioning information PROGN=g810-led +MAJOR=0 +MINOR=2 +MICRO=8 -.PHONY: all debug clean +CXXFLAGS+=-std=gnu++11 -DVERSION=\"$(MAJOR).$(MINOR).$(MICRO)\" +APPSRCS=src/main.cpp src/helpers/*.cpp src/helpers/*.h +LIBSRCS=src/classes/*.cpp src/classes/*.h -all: bin/$(PROGN) +.PHONY: all bin debug clean setup install uninstall lib install-lib install-dev -bin/$(PROGN): src/main.cpp src/classes/*.cpp src/classes/*.h +all: lib/lib$(PROGN).so bin/$(PROGN) + +bin: bin/$(PROGN) + +bin/$(PROGN): $(APPSRCS) $(LIBSRCS) @mkdir -p bin - $(CC) $(CFLAGS) $(LIBUSB_INC) -o $@ $^ $(LDFLAGS) - -debug: CFLAGS += -g -Wextra -pedantic + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) + +debug: CXXFLAGS += -g -Wextra -pedantic debug: bin/$(PROGN) -clean: - rm -rf bin +lib/lib$(PROGN).so: $(LIBSRCS) + @mkdir -p lib + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -fPIC -shared -Wl,-soname,lib$(PROGN).so -o lib/lib$(PROGN).so.$(MAJOR).$(MINOR).$(MICRO) $^ $(LIBS) + @ln -sf lib$(PROGN).so.$(MAJOR).$(MINOR).$(MICRO) lib/lib$(PROGN).so +bin-linked: lib/lib$(PROGN).so + @mkdir -p bin + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) $(APPSRCS) -o bin/$(PROGN) $(LIBS) -L./lib -l$(PROGN) + +lib: lib/lib$(PROGN).so + +clean: + @rm -rf bin + @rm -rf lib + +setup: + @install -m 755 -d \ + $(DESTDIR)/usr/bin \ + $(DESTDIR)/etc/$(PROGN)/samples \ + $(DESTDIR)/etc/udev/rules.d + @cp bin/$(PROGN) $(DESTDIR)/usr/bin + @test -s $(DESTDIR)/usr/bin/g213-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g213-led + @test -s $(DESTDIR)/usr/bin/g410-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g410-led + @test -s $(DESTDIR)/usr/bin/g413-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g413-led + @test -s $(DESTDIR)/usr/bin/g512-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g512-led + @test -s $(DESTDIR)/usr/bin/g513-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g513-led + @test -s $(DESTDIR)/usr/bin/g610-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g610-led + @test -s $(DESTDIR)/usr/bin/g910-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/g910-led + @test -s $(DESTDIR)/usr/bin/gpro-led || ln -s /usr/bin/$(PROGN) $(DESTDIR)/usr/bin/gpro-led + @cp sample_profiles/* $(DESTDIR)/etc/$(PROGN)/samples + @cp udev/$(PROGN).rules $(DESTDIR)/etc/udev/rules.d + @test -s /usr/bin/systemd-run && \ + install -m 755 -d $(DESTDIR)$(SYSTEMDDIR)/system && \ + cp systemd/$(PROGN)-reboot.service $(DESTDIR)$(SYSTEMDDIR)/system + +install-lib: lib + @install -m 755 -d $(libdir) + @install -m 644 lib/lib$(PROGN).so.$(MAJOR).$(MINOR).$(MICRO) $(libdir)/ + @ln -sf lib$(PROGN).so.$(MAJOR).$(MINOR).$(MICRO) $(libdir)/lib$(PROGN).so + +install-dev: install-lib + @mkdir -p $(includedir)/$(PROGN)/ + @install -m 644 src/classes/*.h $(includedir)/$(PROGN) + +install: setup + @test -s /etc/$(PROGN)/profile || \ + cp /etc/$(PROGN)/samples/group_keys /etc/$(PROGN)/profile + @test -s /etc/$(PROGN)/reboot || \ + cp /etc/$(PROGN)/samples/all_off /etc/$(PROGN)/reboot + @udevadm control --reload-rules + @$(PROGN) -p /etc/$(PROGN)/profile + @test -s /usr/bin/systemd-run && \ + systemctl daemon-reload && \ + systemctl enable $(PROGN)-reboot + +uninstall-lib: + @rm -f $(libdir)/lib$(PROGN).so* + +uninstall-dev: + @rm -rf $(includedir)/$(PROGN) + +uninstall: + @test -s /usr/bin/systemd-run && \ + systemctl disable $(PROGN)-reboot && \ + rm $(SYSTEMDDIR)/system/$(PROGN)-reboot.service && \ + systemctl daemon-reload && \ + rm -R /etc/$(PROGN) + + @rm /usr/bin/g213-led + @rm /usr/bin/g410-led + @rm /usr/bin/g413-led + @rm /usr/bin/g413-led + @rm /usr/bin/g512-led + @rm /usr/bin/g513-led + @rm /usr/bin/g610-led + @rm /usr/bin/g910-led + @rm /usr/bin/gpro-led + @rm /usr/bin/$(PROGN) + + @rm /etc/udev/rules.d/$(PROGN).rules + @udevadm control --reload-rules diff --git a/makerelease b/makerelease new file mode 100755 index 0000000..148e1bf --- /dev/null +++ b/makerelease @@ -0,0 +1,57 @@ +#!/bin/bash + +if [ "$1" == "" ]; then + echo "Error: No version provided" + echo "./makerelease 0.0.1" + exit 1 +fi + +ssh -T git@github.com +if [ ! "$?" = "1" ]; then + echo "No Github ssh key loaded exiting..." + exit 1 +fi + +clear +branch=$(git rev-parse --abbrev-ref HEAD) +read -p "Current branch is $branch. Continue ? (y/N)" choice +case "$choice" in + n|N|'' ) + echo "Cancel !" + exit 1 + ;; + y|Y ) echo "Make release...";; + * ) + echo "Cancel !" + exit 1 + ;; +esac + + + +# Ready to update : + +version=$1 + +sed -i "/string version = /c\\\tstring version = \"$version\";" src/helpers/help.cpp +IFS='.' read -ra VPART <<< "$version" +sed -i "/MAJOR=/cMAJOR=${VPART[0]}" makefile +sed -i "/MINOR=/cMINOR=${VPART[1]}" makefile +sed -i "/MICRO=/cMICRO=${VPART[2]}" makefile + +git commit -m "Version $version" makefile src/* +git push + +git checkout master +git merge develop +git push + +git tag -a "v$version" -m "Version $version" +git push --tags + +git checkout $branch + +#wget https://github.com/MatMoul/g810-led/archive/v$version.zip +#wget https://github.com/MatMoul/g810-led/archive/v$version.tar.gz + +#Publish to aur... diff --git a/pictures/logitech_g810-2.jpg b/pictures/logitech_g810-2.jpg deleted file mode 100644 index 0cb5d34..0000000 Binary files a/pictures/logitech_g810-2.jpg and /dev/null differ diff --git a/sample_effects/bash/k2000 b/sample_effects/bash/k2000 new file mode 100755 index 0000000..c5c85d5 --- /dev/null +++ b/sample_effects/bash/k2000 @@ -0,0 +1,86 @@ +#!/bin/bash + +if [ "$1" == "--help" ]; then + echo "k2000 [speed (default:0.01] [colorOff] [colorOn] [colorFade1] [colorFade2]" + exit 0 +fi + +speed=0.01 +colorOff=000000 +colorOn=ff0000 +colorFade1=aa0000 +colorFade2=550000 + +if [ "$1" != "" ]; then + speed=$1 +fi +if [ "$2" != "" ]; then + colorOff=$2 +fi +if [ "$3" != "" ]; then + colorOn=$3 + if [ "$4" != "" ]; then + colorFade1=$4 + else + colorFade1=$colorOn + fi + if [ "$5" != "" ]; then + colorFade2=$5 + else + colorFade2=$colorOn + fi +fi + +setKeys () { + cmd="" + if [ $1 ] ; then + cmd=$cmd"k $1 $colorOn\n" + fi + if [ $2 ] ; then + cmd=$cmd"k $2 $colorFade1\n" + fi + if [ $3 ] ; then + cmd=$cmd"k $3 $colorFade2\n" + fi + if [ $4 ] ; then + cmd=$cmd"k $4 $colorOff\n" + fi + cmd=$cmd"c" + echo -e $cmd | g810-led -pp + sleep $speed +} + +g810-led -gn fkeys $colorOff + +setKeys F1 +setKeys F2 +setKeys F3 +setKeys F4 +setKeys F5 F1 +setKeys F6 F2 F1 +setKeys F7 F3 F2 F1 +setKeys F8 F4 F3 F2 +setKeys F9 F5 F4 F3 +setKeys F10 F6 F5 F4 +setKeys F11 F7 F6 F5 +setKeys F12 F8 F7 F6 +setKeys F12 F9 F8 F7 +setKeys F12 F10 F9 F8 +setKeys F12 F11 F10 F9 +setKeys F11 F10 F10 F10 +setKeys F10 +setKeys F9 +setKeys F8 F12 +setKeys F7 F11 F12 +setKeys F6 F10 F11 F12 +setKeys F5 F9 F10 F11 +setKeys F4 F8 F9 F10 +setKeys F3 F7 F8 F9 +setKeys F2 F6 F7 F8 +setKeys F1 F5 F6 F7 +setKeys F1 F4 F5 F6 +setKeys F1 F3 F4 F5 +setKeys F1 F2 F3 F4 +setKeys F1 F1 F2 F3 +setKeys F1 F1 F1 F2 +setKeys F1 F1 F1 F1 diff --git a/sample_effects/python/k2000 b/sample_effects/python/k2000 new file mode 100755 index 0000000..ce3c031 --- /dev/null +++ b/sample_effects/python/k2000 @@ -0,0 +1,96 @@ +#!/usr/bin/python2 + +import sys +import subprocess +import time + + +if len(sys.argv) > 1: + if sys.argv[1] == '--help': + print 'k2000 [speed (default:0.01] [colorOff] [colorOn] [colorFade1] [colorFade2]' + sys.exit() + + +speed = 0.01 +colorOff = '000000' +colorOn = 'ff0000' +colorFade1 = 'aa0000' +colorFade2 = '550000' + +if len(sys.argv) > 1: + try: + speed = float(sys.argv[1]) + except: + print 'Speed arg error' +if len(sys.argv) > 2: + try: + colorOff = sys.argv[2] + except: + print 'colorOff arg error' +if len(sys.argv) > 3: + try: + colorOn = sys.argv[3] + except: + print 'colorOn arg error' +if len(sys.argv) > 4: + try: + colorFade1 = sys.argv[4] + except: + print 'colorFade1 arg error' +if len(sys.argv) > 5: + try: + colorFade2 = sys.argv[5] + except: + print 'colorFade2 arg error' + + +def setKeys(keys): + pipeValue = '' + for index in range(len(keys)): + if index == 0: + pipeValue = pipeValue + 'k ' + keys[index] + ' ' + colorOn + '\\n' + elif index == 1: + pipeValue = pipeValue + 'k ' + keys[index] + ' ' + colorFade1 + '\\n' + elif index == 2: + pipeValue = pipeValue + 'k ' + keys[index] + ' ' + colorFade2 + '\\n' + elif index == 3: + pipeValue = pipeValue + 'k ' + keys[index] + ' ' + colorOff + '\\n' + pipeValue = pipeValue + 'c' + subprocess.call('echo -e "' + pipeValue + '" | g810-led -pp', shell=True) + time.sleep(speed) + + +subprocess.call('g810-led -gn fkeys ' + colorOff, shell=True) + +setKeys(['F1']) +setKeys(['F2']) +setKeys(['F3']) +setKeys(['F4']) +setKeys(['F5','F1']) +setKeys(['F6','F2','F1']) +setKeys(['F7','F3','F2','F1']) +setKeys(['F8','F4','F3','F2']) +setKeys(['F9','F5','F4','F3']) +setKeys(['F10','F6','F5','F4']) +setKeys(['F11','F7','F6','F5']) +setKeys(['F12','F8','F7','F6']) +setKeys(['F12','F9','F8','F7']) +setKeys(['F12','F10','F9','F8']) +setKeys(['F12','F11','F10','F9']) +setKeys(['F11','F10','F10','F10']) +setKeys(['F10']) +setKeys(['F9']) +setKeys(['F8','F12']) +setKeys(['F7','F11','F12']) +setKeys(['F6','F10','F11','F12']) +setKeys(['F5','F9','F10','F11']) +setKeys(['F4','F8','F9','F10']) +setKeys(['F3','F7','F8','F9']) +setKeys(['F2','F6','F7','F8']) +setKeys(['F1','F5','F6','F7']) +setKeys(['F1','F4','F5','F6']) +setKeys(['F1','F3','F4','F5']) +setKeys(['F1','F2','F3','F4']) +setKeys(['F1','F1','F2','F3']) +setKeys(['F1','F1','F1','F2']) +setKeys(['F1','F1','F1','F1']) diff --git a/sample_profiles/all_blue_fxl_breathing_red b/sample_profiles/all_blue_fxl_breathing_red new file mode 100644 index 0000000..8e8ccf4 --- /dev/null +++ b/sample_profiles/all_blue_fxl_breathing_red @@ -0,0 +1,5 @@ +a 0000ff # Set all keys blue + +c # Commit changes + +fx breathing logo ff0000 10 # Set breathing effect with red color and speed 10 diff --git a/sample_profiles/colors b/sample_profiles/colors new file mode 100644 index 0000000..d87c950 --- /dev/null +++ b/sample_profiles/colors @@ -0,0 +1,28 @@ +# Sample profile using Groups of Keys and Single Characters. + +g logo 000096 # Blue +g indicators ffffff # White +g multimedia 009600 # Green +g fkeys ff7700 # Orange +g modifiers ff7700 # Orange +g arrows 0000ff # Red +g numeric 00ff00 # Green +g functions ffffff # White +g keys ff00ff # Purple +g gkeys ffffff # White +k tilde ff0000 # Red +k W 0000ff # Blue { +k A 0000ff +k S 0000ff +k D 0000ff # } +k 1 ff0000 # Red { +k 2 ff0000 +k 3 ff0000 +k 4 ff0000 +k 5 ff0000 +k 6 ff0000 +k 7 ff0000 +k 8 ff0000 +k 9 ff0000 +k 0 ff0000 # } +c # Commit changes diff --git a/sample_profiles/fx_breathing_red b/sample_profiles/fx_breathing_red new file mode 100644 index 0000000..250349c --- /dev/null +++ b/sample_profiles/fx_breathing_red @@ -0,0 +1,2 @@ + +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 new file mode 100644 index 0000000..97264a7 --- /dev/null +++ b/sample_profiles/fx_color_green @@ -0,0 +1,3 @@ +# Green Profile + +fx color all 00ff00 # Set all keys green diff --git a/sample_profiles/fx_cwave b/sample_profiles/fx_cwave new file mode 100644 index 0000000..347a1bc --- /dev/null +++ b/sample_profiles/fx_cwave @@ -0,0 +1,2 @@ + +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 new file mode 100644 index 0000000..cea0f8a --- /dev/null +++ b/sample_profiles/fx_hwave @@ -0,0 +1,2 @@ + +fx hwave all 20 # Set horizontal wave effect with speed 20 diff --git a/sample_profiles/fx_vwave b/sample_profiles/fx_vwave new file mode 100644 index 0000000..a52aca2 --- /dev/null +++ b/sample_profiles/fx_vwave @@ -0,0 +1,2 @@ + +fx vwave all 20 # Set vertical wave effect with speed 20 diff --git a/sample_profiles/group_keys b/sample_profiles/group_keys index 98afb1a..53c92df 100644 --- a/sample_profiles/group_keys +++ b/sample_profiles/group_keys @@ -1,7 +1,7 @@ # Sample profile by groups keys g logo 000096 -g indicators 00ffff +g indicators ffffff g multimedia 009600 g fkeys ff00ff g modifiers ff0000 @@ -9,5 +9,6 @@ g arrows ffff00 g numeric 00ffff g functions ffffff g keys 009696 +g gkeys ffffff c # Commit changes diff --git a/sample_profiles/keys_v_gradiant_fr_ch-latin1 b/sample_profiles/keys_v_gradiant_fr_ch-latin1 index 0a56625..f22b5f5 100644 --- a/sample_profiles/keys_v_gradiant_fr_ch-latin1 +++ b/sample_profiles/keys_v_gradiant_fr_ch-latin1 @@ -56,7 +56,7 @@ k w $raw3 k e $raw3 k r $raw3 k t $raw3 -k z $raw3 +k y $raw3 k u $raw3 k i $raw3 k o $raw3 @@ -94,7 +94,7 @@ k num_plus $raw4 # Raw 5 : k shift_left $raw5 k intl_backslash $raw5 -k y $raw5 +k z $raw5 k x $raw5 k c $raw5 k v $raw5 diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index 43151f9..9c54f9d 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -1,845 +1,897 @@ #include "Keyboard.h" -#include + +#include #include -#include -#include "libusb.h" +#include + +#if defined(hidapi) + #include + #include "hidapi/hidapi.h" +#elif defined(libusb) + #include "libusb-1.0/libusb.h" +#endif -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; - - 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 == 0xc32b) { // G910 spark - pid = desc.idProduct; - kbdProtocol = KeyboardProtocol::g910; - break; - } - if (desc.idProduct == 0xc335) { // G910 spectrum - pid = desc.idProduct; - kbdProtocol = KeyboardProtocol::g910; - break; - } - } - } - libusb_free_device_list(devs, 1); - if (pid == 0) { - libusb_exit(ctx); - ctx = NULL; - return false; - } - - dev_handle = libusb_open_device_with_vid_pid(ctx, 0x046d, pid); - 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; -} +vector LedKeyboard::listKeyboards() { + vector deviceList; -bool Keyboard::commit() { - if (m_isAttached == false) return false; - bool retval = false; - unsigned char *data = new unsigned char[20]; - switch (kbdProtocol) { - case KeyboardProtocol::generic: - data[0] = 0x11; - data[1] = 0xff; - data[2] = 0x0c; - data[3] = 0x5a; - break; - case KeyboardProtocol::g910: - data[0] = 0x11; - data[1] = 0xff; - data[2] = 0x0f; - data[3] = 0x5d; - break; - default: - return false; - break; - } - for(int i = 4; i < 20; i++) data[i] = 0x00; - retval = sendDataInternal(data, 20); - delete[] data; - return retval; -} + #if defined(hidapi) + if (hid_init() < 0) return deviceList; + + struct hid_device_info *devs, *dev; + devs = hid_enumerate(0x0, 0x0); + dev = devs; + while (dev) { + for (size_t i = 0; i < SupportedKeyboards.size(); i++) { + if (dev->vendor_id == SupportedKeyboards[i][0]) { + if (dev->product_id == SupportedKeyboards[i][1]) { + DeviceInfo deviceInfo; + deviceInfo.vendorID=dev->vendor_id; + deviceInfo.productID=dev->product_id; -bool Keyboard::getKeyAddress(Key key, KeyAddress &keyAddress) { - switch (key) { - case Key::logo: - keyAddress.addressGroup = KeyAddressGroup::logo; - keyAddress.id = 0x01; - break; - case Key::logo2: - keyAddress.addressGroup = KeyAddressGroup::logo; - keyAddress.id = 0x02; - 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; - 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; - 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::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; -} + if (dev->serial_number != NULL) { + char buf[256]; + wcstombs(buf, dev->serial_number, 256); + deviceInfo.serialNumber = string(buf); + } -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; -} + if (dev->manufacturer_string != NULL) + { + char buf[256]; + wcstombs(buf, dev->manufacturer_string, 256); + deviceInfo.manufacturer = string(buf); + } -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); -} + if (dev->product_string != NULL) + { + char buf[256]; + wcstombs(buf, dev->product_string, 256); + deviceInfo.product = string(buf); + } -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 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::sendDataInternal(unsigned char *data, uint16_t data_size) { - if (m_isAttached == false) 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); - usleep(1000); - if (r < 0) return false; - 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; - } - 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; - } - 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]; - 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; - 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++; + deviceList.push_back(deviceInfo); + dev = dev->next; + break; + } } } - setKeysInternal(KeyAddressGroup::keys, keysBlock, keysBlockCount); + if (dev != NULL) dev = dev->next; + } + hid_free_enumeration(devs); + hid_exit(); + + #elif defined(libusb) + libusb_context *ctx = NULL; + if(libusb_init(&m_ctx) < 0) return deviceList; + + libusb_device **devs; + ssize_t cnt = libusb_get_device_list(ctx, &devs); + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor desc; + libusb_get_device_descriptor(device, &desc); + for (int i=0; i<(int)SupportedKeyboards.size(); i++) { + if (desc.idVendor == SupportedKeyboards[i][0]) { + if (desc.idProduct == SupportedKeyboards[i][1]) { + unsigned char buf[256]; + DeviceInfo deviceInfo; + deviceInfo.vendorID=desc.idVendor; + deviceInfo.productID=desc.idProduct; + + if (libusb_open(device, &m_hidHandle) != 0) continue; + + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1) deviceInfo.serialNumber = string((char*)buf); + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) deviceInfo.manufacturer = string((char*)buf); + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) deviceInfo.product = string((char*)buf); + + deviceList.push_back(deviceInfo); + libusb_close(m_hidHandle); + m_hidHandle = NULL; + break; + } + } + } + } + libusb_free_device_list(devs, 1); + + if (m_hidHandle != NULL) { + libusb_close(m_hidHandle); + m_hidHandle = NULL; + } + + libusb_exit(m_ctx); + m_ctx = NULL; + #endif + + return deviceList; +} + + +bool LedKeyboard::isOpen() { + return m_isOpen; +} + +bool LedKeyboard::open() { + if (m_isOpen) return true; + + return open(0x0, 0x0, ""); +} + +bool LedKeyboard::open(uint16_t vendorID, uint16_t productID, string serial) { + if (m_isOpen && ! close()) return false; + currentDevice.model = KeyboardModel::unknown; + + #if defined(hidapi) + if (hid_init() < 0) return false; + + struct hid_device_info *devs, *dev; + devs = hid_enumerate(vendorID, productID); + dev = devs; + wstring wideSerial; + + if (!serial.empty()) { + wchar_t tempSerial[256]; + if (mbstowcs(tempSerial, serial.c_str(), 256) < 1) return false; + wideSerial = wstring(tempSerial); + } + + while (dev) { + for (int i=0; i<(int)SupportedKeyboards.size(); i++) { + if (dev->vendor_id == SupportedKeyboards[i][0] && dev->product_id == SupportedKeyboards[i][1]) { + if (!serial.empty() && dev->serial_number != NULL && wideSerial.compare(dev->serial_number) != 0) break; //Serial didn't match + + if (dev->serial_number != NULL) { + char buf[256]; + wcstombs(buf,dev->serial_number,256); + currentDevice.serialNumber=string(buf); + } + + if (dev->manufacturer_string != NULL) + { + char buf[256]; + wcstombs(buf,dev->manufacturer_string,256); + currentDevice.manufacturer = string(buf); + } + + if (dev->product_string != NULL) + { + char buf[256]; + wcstombs(buf,dev->product_string,256); + currentDevice.product = string(buf); + } + + currentDevice.vendorID = dev->vendor_id; + currentDevice.productID = dev->product_id; + currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; + break; + } + } + if (currentDevice.model != KeyboardModel::unknown) break; + dev = dev->next; + } + + hid_free_enumeration(devs); + + if (! dev) { + currentDevice.model = KeyboardModel::unknown; + hid_exit(); + return false; + } + + if (wideSerial.empty()) m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, NULL); + else m_hidHandle = hid_open(currentDevice.vendorID, currentDevice.productID, wideSerial.c_str()); + + if(m_hidHandle == 0) { + hid_exit(); + return false; + } + + m_isOpen = true; + return true; + + #elif defined(libusb) + if (libusb_init(&m_ctx) < 0) return false; + + libusb_device **devs; + libusb_device *dev = NULL; + ssize_t cnt = libusb_get_device_list(m_ctx, &devs); + if(cnt >= 0) { + for(ssize_t i = 0; i < cnt; i++) { + libusb_device *device = devs[i]; + libusb_device_descriptor desc; + libusb_get_device_descriptor(device, &desc); + + if (vendorID != 0x0 && desc.idVendor != vendorID) continue; + else if (productID != 0x0 && desc.idProduct != productID) continue; + else if (! serial.empty()) { + if (desc.iSerialNumber <= 0) continue; //Device does not populate serial number + + unsigned char buf[256]; + if (libusb_open(device, &m_hidHandle) != 0){ + m_hidHandle = NULL; + continue; + } + + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1 && serial.compare((char*)buf) == 0) { + //Make sure entry is a supported keyboard and get model + for (int i=0; i<(int)SupportedKeyboards.size(); i++) { + if (desc.idVendor == SupportedKeyboards[i][0]) { + if (desc.idProduct == SupportedKeyboards[i][1]) { + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) currentDevice.manufacturer = string((char*)buf); + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) currentDevice.product = string((char*)buf); + currentDevice.serialNumber = serial; + currentDevice.vendorID = desc.idVendor; + currentDevice.productID = desc.idProduct; + currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; + + dev = device; + libusb_close(m_hidHandle); + m_hidHandle = NULL; + break; + } + } + } + } + else { + libusb_close(m_hidHandle); + m_hidHandle = NULL; + continue; //Serial number set but doesn't match + } + } + + //For the case where serial is not specified, find first supported device + for (int i=0; i<(int)SupportedKeyboards.size(); i++) { + if (desc.idVendor == SupportedKeyboards[i][0]) { + if (desc.idProduct == SupportedKeyboards[i][1]) { + unsigned char buf[256]; + if (libusb_open(device, &m_hidHandle) != 0){ + m_hidHandle = NULL; + continue; + } + currentDevice.vendorID = desc.idVendor; + currentDevice.productID = desc.idProduct; + currentDevice.model = (KeyboardModel)SupportedKeyboards[i][2]; + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iManufacturer, buf, 256) >= 1) currentDevice.manufacturer = string((char*)buf); + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iProduct, buf, 256) >= 1) currentDevice.product = string((char*)buf); + if (libusb_get_string_descriptor_ascii(m_hidHandle, desc.iSerialNumber, buf, 256) >= 1) currentDevice.serialNumber = string((char*)buf); + + libusb_close(m_hidHandle); + m_hidHandle=NULL; + break; + } + } + } + if (currentDevice.model != KeyboardModel::unknown) break; + } + libusb_free_device_list(devs, 1); + } + + if (currentDevice.model == KeyboardModel::unknown) { + libusb_exit(m_ctx); + m_ctx = NULL; + return false; + } + + if (dev == NULL) m_hidHandle = libusb_open_device_with_vid_pid(m_ctx, currentDevice.vendorID, currentDevice.productID); + else libusb_open(dev, &m_hidHandle); + + if(m_hidHandle == NULL) { + libusb_exit(m_ctx); + m_ctx = NULL; + return false; + } + + if(libusb_kernel_driver_active(m_hidHandle, 1) == 1) { + if(libusb_detach_kernel_driver(m_hidHandle, 1) != 0) { + libusb_exit(m_ctx); + m_ctx = NULL; + return false; + } + m_isKernellDetached = true; + } + + if(libusb_claim_interface(m_hidHandle, 1) < 0) { + if(m_isKernellDetached==true) { + libusb_attach_kernel_driver(m_hidHandle, 1); + m_isKernellDetached = false; + } + libusb_exit(m_ctx); + m_ctx = NULL; + return false; + } + + m_isOpen = true; + return true; + #endif + + return false; //In case neither is defined +} + +LedKeyboard::DeviceInfo LedKeyboard::getCurrentDevice() { + return currentDevice; +} + +bool LedKeyboard::close() { + if (! m_isOpen) return true; + m_isOpen = false; + + #if defined(hidapi) + hid_close(m_hidHandle); + m_hidHandle = NULL; + hid_exit(); + return true; + #elif defined(libusb) + if (m_hidHandle == NULL) return true; + if(libusb_release_interface(m_hidHandle, 1) != 0) return false; + if(m_isKernellDetached==true) { + libusb_attach_kernel_driver(m_hidHandle, 1); + m_isKernellDetached = false; + } + libusb_close(m_hidHandle); + m_hidHandle = NULL; + libusb_exit(m_ctx); + m_ctx = NULL; + return true; + #endif + + return false; +} + + +LedKeyboard::KeyboardModel LedKeyboard::getKeyboardModel() { + return currentDevice.model; +} + +bool LedKeyboard::commit() { + byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g213: + case KeyboardModel::g413: + return true; // Keyboard is non-transactional + case KeyboardModel::g410: + case KeyboardModel::g513: + case KeyboardModel::g610: + case KeyboardModel::g810: + case KeyboardModel::gpro: + data = { 0x11, 0xff, 0x0c, 0x5a }; + break; + case KeyboardModel::g910: + data = { 0x11, 0xff, 0x0f, 0x5d }; + break; + default: + return false; + } + data.resize(20, 0x00); + return sendDataInternal(data); +} + +bool LedKeyboard::setKey(LedKeyboard::KeyValue keyValue) { + return setKeys(KeyValueArray {keyValue}); +} + +bool LedKeyboard::setKeys(KeyValueArray keyValues) { + if (keyValues.empty()) return false; + + bool retval = true; + + vector> SortedKeys = { + {}, // Logo AddressGroup + {}, // Indicators AddressGroup + {}, // Multimedia AddressGroup + {}, // GKeys AddressGroup + {} // Keys AddressGroup + }; + + for (uint8_t i = 0; i < keyValues.size(); i++) { + switch(static_cast(static_cast(keyValues[i].key) >> 8 )) { + case LedKeyboard::KeyAddressGroup::logo: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[0].size() <= 1 && keyValues[i].key == LedKeyboard::Key::logo) + SortedKeys[0].push_back(keyValues[i]); + break; + case LedKeyboard::KeyboardModel::g910: + if (SortedKeys[0].size() <= 2) SortedKeys[0].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::indicators: + if (SortedKeys[1].size() <= 5) SortedKeys[1].push_back(keyValues[i]); + break; + case LedKeyboard::KeyAddressGroup::multimedia: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[2].size() <= 5) SortedKeys[2].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::gkeys: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g910: + if (SortedKeys[3].size() <= 9) SortedKeys[3].push_back(keyValues[i]); + break; + default: + break; + } + break; + case LedKeyboard::KeyAddressGroup::keys: + switch (currentDevice.model) { + case LedKeyboard::KeyboardModel::g610: + case LedKeyboard::KeyboardModel::g810: + case LedKeyboard::KeyboardModel::g910: + case LedKeyboard::KeyboardModel::gpro: + if (SortedKeys[4].size() <= 120) SortedKeys[4].push_back(keyValues[i]); + break; + case LedKeyboard::KeyboardModel::g410: + if (SortedKeys[4].size() <= 120) + if (keyValues[i].key < LedKeyboard::Key::num_lock || + keyValues[i].key > LedKeyboard::Key::num_dot) + SortedKeys[4].push_back(keyValues[i]); + break; + default: + break; + } + break; } } - 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; + 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; + } + + } } - setKeys(keyValues, 127); - return true; + return retval; } -bool Keyboard::setGroupKeys(KeyGroup keyGroup, KeyColors colors) { - KeyValue keyValues[54]; - int keyValuesCount = 0; +bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) { + KeyValueArray keyValues; + + KeyArray keyArray; + 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); + keyArray = keyGroupLogo; 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); + keyArray = keyGroupIndicators; 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); + keyArray = keyGroupGKeys; + break; + case KeyGroup::multimedia: + keyArray = keyGroupMultimedia; + break; + case KeyGroup::fkeys: + keyArray = keyGroupFKeys; + break; + case KeyGroup::modifiers: + keyArray = keyGroupModifiers; + break; + case KeyGroup::arrows: + keyArray = keyGroupArrows; + break; + case KeyGroup::numeric: + keyArray = keyGroupNumeric; + break; + case KeyGroup::functions: + keyArray = keyGroupFunctions; + break; + case KeyGroup::keys: + keyArray = keyGroupKeys; + break; + default: break; } - return true; + + for (uint8_t i = 0; i < keyArray.size(); i++) keyValues.push_back({keyArray[i], color}); + + return setKeys(keyValues); +} + +bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { + KeyValueArray keyValues; + + switch (currentDevice.model) { + case KeyboardModel::g213: + for (uint8_t rIndex=0x01; rIndex <= 0x05; rIndex++) if (! setRegion(rIndex, color)) return false; + return true; + case KeyboardModel::g413: + setNativeEffect(NativeEffect::color, NativeEffectPart::keys, 0, color); + return true; + case KeyboardModel::g410: + case KeyboardModel::g513: + case KeyboardModel::g610: + case KeyboardModel::g810: + case KeyboardModel::g910: + case KeyboardModel::gpro: + 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); + default: + return false; + } + return false; +} + + +bool LedKeyboard::setMRKey(uint8_t value) { + LedKeyboard::byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g910: + switch (value) { + case 0x00: + case 0x01: + data = { 0x11, 0xff, 0x0a, 0x0e, value }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; + default: + break; + } + return false; +} + +bool LedKeyboard::setMNKey(uint8_t value) { + LedKeyboard::byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g910: + switch (value) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + data = { 0x11, 0xff, 0x09, 0x1e, value }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; + default: + break; + } + return false; +} + +bool LedKeyboard::setGKeysMode(uint8_t value) { + LedKeyboard::byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g910: + switch (value) { + case 0x00: + case 0x01: + data = { 0x11, 0xff, 0x08, 0x2e, value }; + data.resize(20, 0x00); + return sendDataInternal(data); + default: + break; + } + break; + default: + break; + } + return false; +} + +bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) { + LedKeyboard::byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g213: + data = { 0x11, 0xff, 0x0c, 0x3a, region, 0x01, color.red, color.green, color.blue }; + data.resize(20,0x00); + return sendDataInternal(data); + break; + default: + break; + } + + return false; +} + +bool LedKeyboard::setStartupMode(StartupMode startupMode) { + byte_buffer_t data; + switch (currentDevice.model) { + case KeyboardModel::g213: + case KeyboardModel::g410: + case KeyboardModel::g610: + case KeyboardModel::g810: + case KeyboardModel::gpro: + 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 LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, uint8_t speed, Color color) { + uint8_t protocolByte = 0; + + // NativeEffectPart::all is not in the device protocol, but an alias for both keys and logo, plus indicators + if (part == LedKeyboard::NativeEffectPart::all) { + switch (effect) { + case LedKeyboard::NativeEffect::color: + if (! setGroupKeys(LedKeyboard::KeyGroup::indicators, color)) return false; + if (! commit()) return false; + break; + case LedKeyboard::NativeEffect::breathing: + if (! setGroupKeys(LedKeyboard::KeyGroup::indicators, color)) return false;; + if (! commit()) return false;; + break; + case LedKeyboard::NativeEffect::cycle: + case LedKeyboard::NativeEffect::hwave: + case LedKeyboard::NativeEffect::vwave: + case LedKeyboard::NativeEffect::cwave: + if (! setGroupKeys( + LedKeyboard::KeyGroup::indicators, + LedKeyboard::Color({0xff, 0xff, 0xff})) + ) return false; + if (! commit()) return false; + break; + } + return ( + setNativeEffect(effect, LedKeyboard::NativeEffectPart::keys, speed, color) && + setNativeEffect(effect, LedKeyboard::NativeEffectPart::logo, speed, color)); + } + + switch (currentDevice.model) { + case KeyboardModel::g213: + case KeyboardModel::g413: + protocolByte = 0x0c; + if (part == NativeEffectPart::logo) return true; //Does not have logo component + break; + case KeyboardModel::g410: + case KeyboardModel::g513: + case KeyboardModel::g610: // Unconfirmed + case KeyboardModel::g810: + case KeyboardModel::gpro: + protocolByte = 0x0d; + break; + case KeyboardModel::g910: + protocolByte = 0x10; + break; + default: + return false; + } + + byte_buffer_t data; + + switch (effect) { + + case NativeEffect::color: + data = { 0x11, 0xff, protocolByte, 0x3c, (uint8_t)part, 0x01, color.red, color.green, color.blue, 0x02 }; + break; + case NativeEffect::breathing: + data = { + 0x11, 0xff, protocolByte, 0x3c, (uint8_t)part, 0x02, + color.red, color.green, color.blue, speed, + 0x10, 0x00, 0x64 + }; + break; + case NativeEffect::cycle: + data = { + 0x11, 0xff, protocolByte, 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, protocolByte, 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, protocolByte, 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, protocolByte, 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 LedKeyboard::sendDataInternal(byte_buffer_t &data) { + if (data.size() > 0) { + #if defined(hidapi) + if (! open(currentDevice.vendorID, currentDevice.productID, currentDevice.serialNumber)) return false; + data.insert(data.begin(), 0x00); + if (hid_write(m_hidHandle, const_cast(data.data()), data.size()) < 0) { + std::cout<<"Error: Can not write to hidraw, try with the libusb version"<(data2.data()), data2.size(), 1); + */ + return true; + #elif defined(libusb) + if (! m_isOpen) return false; + if (data.size() > 20) { + if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0212, 1, + const_cast(data.data()), data.size(), 2000) < 0) + return false; + } else { + if(libusb_control_transfer(m_hidHandle, 0x21, 0x09, 0x0211, 1, + const_cast(data.data()), data.size(), 2000) < 0) + return false; + } + usleep(1000); + unsigned char buffer[64]; + int len = 0; + libusb_interrupt_transfer(m_hidHandle, 0x82, buffer, sizeof(buffer), &len, 1); + return true; + #endif + } + + return false; +} + +LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddressGroup keyAddressGroup) { + switch (currentDevice.model) { + case KeyboardModel::g213: + case KeyboardModel::g413: + return {}; // Device doesn't support per-key setting + case KeyboardModel::g410: + case KeyboardModel::g513: + case KeyboardModel::g610: + case KeyboardModel::g810: + case KeyboardModel::gpro: + 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 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: + break; + } + return {}; } diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index a2b563e..76e178f 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -1,70 +1,223 @@ -#ifndef DEF_KEYBOARD -#define DEF_KEYBOARD +#ifndef KEYBOARD_CLASS +#define KEYBOARD_CLASS #include -#include +#include -class Keyboard { +#if defined(hidapi) + #include "hidapi/hidapi.h" +#elif defined(libusb) + #include "libusb-1.0/libusb.h" +#endif + + +class LedKeyboard { + + private: + + 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 + std::vector> SupportedKeyboards = { + { 0x46d, 0xc336, (u_int16_t)KeyboardModel::g213 }, + { 0x46d, 0xc330, (u_int16_t)KeyboardModel::g410 }, + { 0x46d, 0xc33a, (u_int16_t)KeyboardModel::g413 }, + { 0x46d, 0xc33c, (u_int16_t)KeyboardModel::g513 }, + { 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 }, + { 0x46d, 0xc339, (u_int16_t)KeyboardModel::gpro } }; - 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; }; + enum class KeyboardModel : uint8_t { + unknown = 0x00, + g213, + g410, + g413, + g513, + g610, + g810, + g910, + gpro + }; + 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 + + }; + + typedef struct { + uint16_t vendorID = 0x0; + uint16_t productID = 0x0; + std::string manufacturer = ""; + std::string product = ""; + std::string serialNumber = ""; + KeyboardModel model; + } DeviceInfo; + + struct Color { + uint8_t red; + uint8_t green; + uint8_t blue; + }; + struct KeyValue { + LedKeyboard::Key key; + LedKeyboard::Color color; + }; + + typedef std::vector KeyValueArray; + + + ~LedKeyboard(); + + + std::vector listKeyboards(); + + bool isOpen(); + bool open(); + bool open(uint16_t vendorID, uint16_t productID, std::string serial); + DeviceInfo getCurrentDevice(); + bool close(); + + KeyboardModel getKeyboardModel(); - 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[], size_t keyValueCount); - bool setAllKeys(KeyColors colors); - bool setGroupKeys(KeyGroup keyGroup, KeyColors colors); + bool setKeys(KeyValueArray keyValues); + bool setGroupKeys(KeyGroup keyGroup, Color color); + bool setAllKeys(Color color); + + bool setMRKey(uint8_t value); + bool setMNKey(uint8_t value); + bool setGKeysMode(uint8_t value); + + bool setRegion(uint8_t region, 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 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::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; + DeviceInfo currentDevice; + + #if defined(hidapi) + hid_device *m_hidHandle; + #elif defined(libusb) + bool m_isKernellDetached = false; + libusb_device_handle *m_hidHandle; + libusb_context *m_ctx = NULL; + #endif + + + bool sendDataInternal(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..eb95f87 --- /dev/null +++ b/src/helpers/help.cpp @@ -0,0 +1,330 @@ +#include "help.h" + +#include +#include "utils.h" + + +using namespace std; + +namespace help { + + inline KeyboardFeatures operator|(KeyboardFeatures a, KeyboardFeatures b) { + return static_cast(static_cast(a) | static_cast(b)); + } + + KeyboardFeatures getKeyboardFeatures(string cmdName) { + if(cmdName == "g213-led") return KeyboardFeatures::g213; + else if(cmdName == "g410-led") return KeyboardFeatures::g410; + else if(cmdName == "g413-led") return KeyboardFeatures::g413; + else if(cmdName == "g610-led") return KeyboardFeatures::g610; + else if(cmdName == "g810-led") return KeyboardFeatures::g810; + else if(cmdName == "g910-led") return KeyboardFeatures::g910; + else if(cmdName == "gpro-led") return KeyboardFeatures::gpro; + return KeyboardFeatures::all; + } + + + void usage(char *arg0) { + string cmdName = utils::getCmdName(arg0); + KeyboardFeatures features = getKeyboardFeatures(cmdName); + cout< + +namespace help { + + enum class KeyboardFeatures : uint16_t { + none = 0, + rgb = 1, + intensity = 2, + commit = 4, + logo1 = 8, + logo2 = 16, + numpad = 32, + multimedia = 64, + gkeys = 128, + setall = 256, + setgroup = 512, + setkey = 1024, + setregion = 2048, + setindicators = 4096, + poweronfx = 8192, + // fx features + + all = rgb | intensity | commit | logo1 | logo2 | numpad | multimedia | gkeys | + setall | setgroup | setkey | setregion | setindicators | poweronfx, + + g213 = rgb | logo1 | numpad | multimedia | setall | setregion | setindicators | poweronfx, + g410 = rgb | commit | setall | setgroup | setkey | poweronfx, + g413 = intensity | setall, + g610 = intensity | commit | logo1 | numpad | multimedia | setall | setgroup | setkey | setindicators | poweronfx, + g810 = rgb | commit | logo1 | numpad | multimedia | setall | setgroup | setkey | setindicators | poweronfx, + g910 = rgb | commit | logo1 | logo2 | numpad | multimedia | gkeys | setall | setgroup | setkey | setindicators | poweronfx, + gpro = rgb | commit | logo1 | multimedia | setall | setgroup | setkey | setindicators | poweronfx + }; + inline KeyboardFeatures operator|(KeyboardFeatures a, KeyboardFeatures b); + + KeyboardFeatures getKeyboardFeatures(std::string cmdName); + + void usage(char *arg0); + void keys(char *arg0); + void effects(char *arg0); + void samples(char *arg0); + +} + +#ifndef VERSION +#define VERSION "unspecified" +#endif + +#endif diff --git a/src/helpers/utils.cpp b/src/helpers/utils.cpp new file mode 100644 index 0000000..5398838 --- /dev/null +++ b/src/helpers/utils.cpp @@ -0,0 +1,228 @@ +#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; + } + + bool parseUInt8(std::string val, uint8_t &uint8) { + if (val.length() == 1) val = "0" + val; + if (val.length() != 2) return false; + uint8 = std::stoul("0x" + val, nullptr, 16); + return true; + } + + bool parseUInt16(std::string val, uint16_t &uint16) { + if (val.length() == 1) val = "0" + val; + if (val.length() == 2) val = "0" + val; + if (val.length() == 3) val = "0" + val; + if (val.length() != 4) return false; + uint16 = 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..92de26b --- /dev/null +++ b/src/helpers/utils.h @@ -0,0 +1,23 @@ +#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); + bool parseUInt8(std::string val, uint8_t &uint8); + bool parseUInt16(std::string val, uint16_t &uint16); + +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index b7af4eb..467589a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,310 +1,310 @@ -#include -#include +#include +#include +#include #include +#include + +#include "helpers/help.h" +#include "helpers/utils.h" #include "classes/Keyboard.h" -using namespace std; -void usage() { - string appname = "g810-led"; - cout< deviceList = kbd.listKeyboards(); + if (deviceList.empty()) { + std::cout<<"Matching or compatible device not found !"<::iterator iterator; + for (iterator = deviceList.begin(); iterator != deviceList.end(); iterator++) { + LedKeyboard::DeviceInfo device = *iterator; + printDeviceInfo(device); + } + return 0; } -int setStartupEffect(string effect) { - Keyboard lg_kbd; - Keyboard::PowerOnEffect powerOnEffect; - if (lg_kbd.parsePowerOnEffect(effect, powerOnEffect) == true) { - lg_kbd.attach(); - lg_kbd.setPowerOnEffect(powerOnEffect); - lg_kbd.commit(); - lg_kbd.detach(); - return 0; - } +int setAllKeys(LedKeyboard &kbd, std::string arg2, bool commit = true) { + LedKeyboard::Color color; + if (! utils::parseColor(arg2, color)) return 1; + if (! kbd.open()) return 1; + if(! kbd.setAllKeys(color)) return 1; + if (commit) if(! kbd.commit()) return 1; + return 0; +} + +int setGroupKeys(LedKeyboard &kbd, std::string arg2, std::string arg3, bool commit = true) { + LedKeyboard::KeyGroup keyGroup; + LedKeyboard::Color color; + if (! utils::parseKeyGroup(arg2, keyGroup)) return 1; + if (! utils::parseColor(arg3, color)) return 1; + if (! kbd.open()) return 1; + if (! kbd.setGroupKeys(keyGroup, color)) return 1; + if (commit) if(! kbd.commit()) return 1; + return 0; +} + +int setKey(LedKeyboard &kbd, std::string arg2, std::string arg3, bool commit = true) { + LedKeyboard::Key key; + LedKeyboard::Color color; + if (! utils::parseKey(arg2, key)) return 1; + if (! utils::parseColor(arg3, color)) return 1; + LedKeyboard::KeyValue keyValue = { key, color }; + if (! kbd.open()) return 1; + if (! kbd.setKey(keyValue)) return 1; + if (commit) if(! kbd.commit()) return 1; + return 0; +} + +int setMRKey(LedKeyboard &kbd, std::string arg2) { + uint8_t value; + if (! utils::parseUInt8(arg2, value)) return 1; + if (! kbd.open()) return 1; + if (! kbd.setMRKey(value)) return 1; + return 0; +} + +int setMNKey(LedKeyboard &kbd, std::string arg2) { + uint8_t value; + if (! utils::parseUInt8(arg2, value)) return 1; + if (! kbd.open()) return 1; + if (! kbd.setMNKey(value)) return 1; + return 0; +} + +int setGKeysMode(LedKeyboard &kbd, std::string arg2) { + uint8_t value; + if (! utils::parseUInt8(arg2, value)) return 1; + if (! kbd.open()) return 1; + if (! kbd.setGKeysMode(value)) return 1; + return 0; +} + +int setRegion(LedKeyboard &kbd, std::string arg2, std::string arg3) { + uint8_t region = 0; + LedKeyboard::Color color; + if (! utils::parseColor(arg3, color)) return 1; + if (! utils::parseUInt8(arg2, region)) return 1; + if (kbd.setRegion(region, color)) return 0; return 1; } -int setKey(string key, string color, bool commit) { - Keyboard lg_kbd; - Keyboard::KeyAddress keyAddress; - if (lg_kbd.parseKey(key, keyAddress) == true) { - Keyboard::KeyColors colors; - if (lg_kbd.parseColor(color, colors) == true) { - Keyboard::KeyValue keyValue; - keyValue.key = keyAddress; - keyValue.colors = colors; - lg_kbd.attach(); - lg_kbd.setKey(keyValue); - if (commit == true) lg_kbd.commit(); - lg_kbd.detach(); - return 0; - } +int setFX(LedKeyboard &kbd, std::string arg2, std::string arg3, std::string arg4, std::string arg5 = "") { + LedKeyboard::NativeEffect effect; + LedKeyboard::NativeEffectPart effectPart; + uint8_t speed = 0; + LedKeyboard::Color color; + if (! utils::parseNativeEffect(arg2, effect)) return 1; + if (! utils::parseNativeEffectPart(arg3, effectPart)) return 1; + + switch (effect) { + case LedKeyboard::NativeEffect::color: + if (! utils::parseColor(arg4, color)) return 1; + break; + case LedKeyboard::NativeEffect::breathing: + if (! utils::parseColor(arg4, color)) return 1; + if (arg5 == "") return 1; + if (! utils::parseSpeed(arg5, speed)) return 1; + break; + case LedKeyboard::NativeEffect::cycle: + case LedKeyboard::NativeEffect::hwave: + case LedKeyboard::NativeEffect::vwave: + case LedKeyboard::NativeEffect::cwave: + if (! utils::parseSpeed(arg4, speed)) return 1; + break; } + + if (! kbd.open()) return 1; + + if (! kbd.setNativeEffect(effect, effectPart, speed, color)) return 1; + + return 0; +} + + +int setStartupMode(LedKeyboard &kbd, std::string arg2) { + LedKeyboard::StartupMode startupMode; + if (! utils::parseStartupMode(arg2, startupMode)) return 1; + if (! kbd.open()) return 1; + if (kbd.setStartupMode(startupMode)) return 0; return 1; } -int setAllKeys(string color, bool commit) { - Keyboard lg_kbd; - Keyboard::KeyColors colors; - if (lg_kbd.parseColor(color, colors) == true) { - lg_kbd.attach(); - lg_kbd.setAllKeys(colors); - if (commit == true) lg_kbd.commit(); - lg_kbd.detach(); - return 0; - } - return 1; -} -int setGroupKeys(string groupKeys, string color, bool commit) { - Keyboard lg_kbd; - Keyboard::KeyGroup keyGroup; - if (lg_kbd.parseKeyGroup(groupKeys, keyGroup) == true) { - Keyboard::KeyColors colors; - if (lg_kbd.parseColor(color, colors) == true) { - lg_kbd.attach(); - lg_kbd.setGroupKeys(keyGroup, colors); - if (commit == true) lg_kbd.commit(); - lg_kbd.detach(); - return 0; - } - } - return 1; -} - -int loadProfile(string profileFile) { - ifstream file; - - file.open(profileFile); - if (file.is_open()) { - - string line; - int lineCount = 1; - int ind; - - Keyboard lg_kbd; - Keyboard::KeyGroup keyGroup; - Keyboard::KeyAddress keyAddress; - Keyboard::KeyValue keyValue; - Keyboard::KeyColors colors; - - map var; - vector keys; - - lg_kbd.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 (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] == "r" && args.size() > 2) { + if (setRegion(kbd, args[1], args[2]) == 1) retval = 1; + } else if (args[0] == "mr" && args.size() > 1) { + if (setMRKey(kbd, args[1]) == 1) retval = 1; + } else if (args[0] == "mn" && args.size() > 1) { + if (setMNKey(kbd, args[1]) == 1) retval = 1; + } else if (args[0] == "gkm" && args.size() > 1) { + if (setGKeysMode(kbd, args[1]) == 1) retval = 1; + } else if (args[0] == "fx" && args.size() > 4) { + if (setFX(kbd, args[1], args[2], args[3], args[4]) == 1) retval = 1; + } else if (args[0] == "fx" && args.size() > 3) { + if (setFX(kbd, args[1], args[2], args[3]) == 1) retval = 1; } - - lineCount++; } - - lg_kbd.detach(); - + } + return retval; +} + +int loadProfile(LedKeyboard &kbd, char *arg2) { + std::ifstream file; + file.open(arg2); + if (file.is_open()) { + int retval = 0; + retval = parseProfile(kbd, file); file.close(); - - return 0; + return retval; } return 1; } -int main(int argc, char *argv[]) { - string str = argv[0]; - size_t split = str.find_last_of("/\\"); - str = str.substr(split + 1); - 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]); - } - usage(); - return 1; +int pipeProfile(LedKeyboard &kbd) { + if (isatty(fileno(stdin))) return 1; + return parseProfile(kbd, std::cin); +} + + + +int main(int argc, char **argv) { + if (argc < 2) { + help::usage(argv[0]); + return 1; + } + + LedKeyboard kbd; + std::string serial; + uint16_t vendorID = 0x0; + uint16_t productID = 0x0; + + int argIndex = 1; + while (argIndex < argc) + { + std::string arg = argv[argIndex]; + + // Non-Command arguments + if (argc > (argIndex + 1) && arg == "-ds") { + serial = argv[argIndex + 1]; + argIndex += 2; + continue; + } else if (argc > (argIndex + 1) && arg == "-dv"){ + if (! utils::parseUInt16(argv[argIndex + 1], vendorID)) return 1; + argIndex += 2; + continue; + } else if (argc > (argIndex + 1) && arg == "-dp"){ + if (! utils::parseUInt16(argv[argIndex + 1], productID)) return 1; + argIndex += 2; + continue; + } else if (argc > (argIndex + 1) && arg == "-tuk"){ + uint8_t kbdProtocol = 0; + if (! utils::parseUInt8(argv[argIndex + 1], kbdProtocol)) return 1; + switch(kbdProtocol) { + case 1: + kbd.SupportedKeyboards = { { vendorID, productID, (u_int16_t)LedKeyboard::KeyboardModel::g810 } }; + break; + case 2: + kbd.SupportedKeyboards = { { vendorID, productID, (u_int16_t)LedKeyboard::KeyboardModel::g910 } }; + break; + case 3: + kbd.SupportedKeyboards = { { vendorID, productID, (u_int16_t)LedKeyboard::KeyboardModel::g213 } }; + break; + default: + break; + } + argIndex += 2; + continue; + } + + + //Commands that do not need to initialize a specific device + if (arg == "--help" || arg == "-h") {help::usage(argv[0]); return 0;} + else if (arg == "--list-keyboards") return listKeyboards(kbd); + else if (arg == "--help-keys") {help::keys(argv[0]); return 0;} + else if (arg == "--help-effects") {help::effects(argv[0]); return 0;} + else if (arg == "--help-samples") {help::samples(argv[0]); return 0;} + + //Initialize the device for use + if (!kbd.open(vendorID, productID, serial)) { + std::cout << "Matching or compatible device not found !" << std::endl; + return 2; + } + + // Command arguments, these will cause parsing to ignore anything beyond the command and its arguments + if (arg == "-c") return commit(kbd); + else if (arg == "--print-device") {printDeviceInfo(kbd.getCurrentDevice()); return 0;} + else if (argc > (argIndex + 1) && arg == "-a") return setAllKeys(kbd, argv[argIndex + 1]); + else if (argc > (argIndex + 2) && arg == "-g") return setGroupKeys(kbd, argv[argIndex + 1], argv[argIndex + 2]); + else if (argc > (argIndex + 2) && arg == "-k") return setKey(kbd, argv[argIndex + 1], argv[argIndex + 2]); + else if (argc > (argIndex + 1) && arg == "-mr") return setMRKey(kbd, argv[argIndex + 1]); + else if (argc > (argIndex + 1) && arg == "-mn") return setMNKey(kbd, argv[argIndex + 1]); + else if (argc > (argIndex + 1) && arg == "-an") return setAllKeys(kbd, argv[argIndex + 1], false); + else if (argc > (argIndex + 2) && arg == "-gn") + return setGroupKeys(kbd, argv[argIndex + 1], argv[argIndex + 2], false); + else if (argc > (argIndex + 2) && arg == "-kn") return setKey(kbd, argv[argIndex + 1], argv[argIndex + 2], false); + else if (argc > (argIndex + 2) && arg == "-r") return setRegion(kbd, argv[argIndex + 1], argv[argIndex + 2]); + else if (argc > (argIndex + 1) && arg == "-gkm") return setGKeysMode(kbd, argv[argIndex + 1]); + else if (argc > (argIndex + 1) && arg == "-p") return loadProfile(kbd, argv[argIndex + 1]); + else if (arg == "-pp") return pipeProfile(kbd); + else if (argc > (argIndex + 4) && arg == "-fx") + return setFX(kbd, argv[argIndex + 1], argv[argIndex + 2], argv[argIndex + 3], argv[argIndex + 4]); + else if (argc > (argIndex + 3) && arg == "-fx") + return setFX(kbd, argv[argIndex + 1], argv[argIndex + 2], argv[argIndex + 3]); + else if (argc > (argIndex + 1) && arg == "--startup-mode") return setStartupMode(kbd, argv[argIndex + 1]); + else { help::usage(argv[0]); return 1; } + } + + return 0; } diff --git a/systemd/g810-led.service b/systemd/g810-led.service index 4d4b73e..6013066 100644 --- a/systemd/g810-led.service +++ b/systemd/g810-led.service @@ -2,9 +2,9 @@ Description=Set Logitech G810 Led Profile [Service] -ExecStart=/bin/g810-led -p /etc/g810-led/profile +ExecStart=/usr/bin/g810-led -p /etc/g810-led/profile +Type=oneshot +RemainAfterExit=yes [Install] WantedBy=multi-user.target -Type=oneshot -RemainAfterExit=yes diff --git a/udev/g810-led.rules b/udev/g810-led.rules new file mode 100644 index 0000000..08c0d63 --- /dev/null +++ b/udev/g810-led.rules @@ -0,0 +1,11 @@ +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c336", MODE="666" RUN+="/usr/bin/g213-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c330", MODE="666" RUN+="/usr/bin/g410-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c33a", MODE="666" RUN+="/usr/bin/g413-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c33c", MODE="666" RUN+="/usr/bin/g513-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c333", MODE="666" RUN+="/usr/bin/g610-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c338", MODE="666" RUN+="/usr/bin/g610-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="666" RUN+="/usr/bin/g810-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="666" RUN+="/usr/bin/g910-led -p /etc/g810-led/profile" +ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c339", MODE="666" RUN+="/usr/bin/gpro-led -p /etc/g810-led/profile" diff --git a/udev/g810.rules b/udev/g810.rules deleted file mode 100644 index de8dd79..0000000 --- a/udev/g810.rules +++ /dev/null @@ -1,6 +0,0 @@ -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c331", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c337", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c330", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c333", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c32b", MODE="660", GROUP="users" -ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c335", MODE="660", GROUP="users" diff --git a/wireshark_dumps/g810-spectrum/README.md b/wireshark_dumps/g810-spectrum/README.md deleted file mode 100644 index 5c0b6dc..0000000 --- a/wireshark_dumps/g810-spectrum/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Description of each wireshark dump found in this folder -=== - -Sets effect to 'breathing' with color rgb(252,253,254) at the highest level the slider bar offers. Noticed that the full cycle of updates after switching to the profile (which was done through linking a profile to Notepad++ and letting logitech automatically send the profile once) is around 1 second for fullspeed, 5 seconds for midspeed, and a long 10 seconds for nospeed. - -* g810-effect-to-breathing-252-253-254-fullspeed.pcapng -* g810-effect-to-breathing-252-253-254-midspeed.pcapng -* g810-effect-to-breathing-252-253-254-nospeed.pcapng - -Sets effect to 'key press' with pressed color rgb(3,2,1) and background color rgb(252,253,254) with slider at lowest speed - -* g810-effect-to-keypress-3-2-1_252-253-254-nospeed.pcapng - -Idle g810 capture, was getting periodic updates without having anything interesting going on. Not sure why - -* g810-idle.pcapng - -Sets key color of 'a' / 'rcntrl' to rgb(252,253,254) - -* g810-set-a-to-252-253-254.pcapng -* g810-set-rcntrl-to-252-253-254.pcapng - -Sets effect to 'fixedcolor' - believe this was also at rgb(252,253,254). The second one includes going to the window and back, where it loads the profile and then reloads the former profile. - -* g810-switches-to-fixedcolor-effect.pcapng -* g810-switches-to-from-fixedcolor-effect.pcapng diff --git a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-fullspeed.pcapng b/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-fullspeed.pcapng deleted file mode 100644 index 6f02103..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-fullspeed.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-midspeed.pcapng b/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-midspeed.pcapng deleted file mode 100644 index c5c4b97..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-midspeed.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-nospeed.pcapng b/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-nospeed.pcapng deleted file mode 100644 index e74ee6b..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-effect-to-breathing-252-253-254-nospeed.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-effect-to-keypress-3-2-1_252-253-254-nospeed.pcapng b/wireshark_dumps/g810-spectrum/g810-effect-to-keypress-3-2-1_252-253-254-nospeed.pcapng deleted file mode 100644 index 03986f5..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-effect-to-keypress-3-2-1_252-253-254-nospeed.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-idle.pcapng b/wireshark_dumps/g810-spectrum/g810-idle.pcapng deleted file mode 100644 index b38822f..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-idle.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-set-a-to-252-253-254.pcapng b/wireshark_dumps/g810-spectrum/g810-set-a-to-252-253-254.pcapng deleted file mode 100644 index 31f9f87..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-set-a-to-252-253-254.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-set-rcntrl-to-252-253-254.pcapng b/wireshark_dumps/g810-spectrum/g810-set-rcntrl-to-252-253-254.pcapng deleted file mode 100644 index aa848d1..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-set-rcntrl-to-252-253-254.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-switches-to-fixedcolor-effect.pcapng b/wireshark_dumps/g810-spectrum/g810-switches-to-fixedcolor-effect.pcapng deleted file mode 100644 index caa928c..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-switches-to-fixedcolor-effect.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/g810-switches-to-from-fixedcolor-effect.pcapng b/wireshark_dumps/g810-spectrum/g810-switches-to-from-fixedcolor-effect.pcapng deleted file mode 100644 index 12f3023..0000000 Binary files a/wireshark_dumps/g810-spectrum/g810-switches-to-from-fixedcolor-effect.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/set_boot_color.pcapng b/wireshark_dumps/g810-spectrum/set_boot_color.pcapng deleted file mode 100644 index ca2d889..0000000 Binary files a/wireshark_dumps/g810-spectrum/set_boot_color.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/set_boot_rainbow.pcapng b/wireshark_dumps/g810-spectrum/set_boot_rainbow.pcapng deleted file mode 100644 index 61e3c8e..0000000 Binary files a/wireshark_dumps/g810-spectrum/set_boot_rainbow.pcapng and /dev/null differ diff --git a/wireshark_dumps/g810-spectrum/set_keys_colors.pcapng b/wireshark_dumps/g810-spectrum/set_keys_colors.pcapng deleted file mode 100644 index ec4dceb..0000000 Binary files a/wireshark_dumps/g810-spectrum/set_keys_colors.pcapng and /dev/null differ diff --git a/wireshark_dumps/g910-spark/G910_test_blue.pcapng b/wireshark_dumps/g910-spark/G910_test_blue.pcapng deleted file mode 100755 index 5e287a8..0000000 Binary files a/wireshark_dumps/g910-spark/G910_test_blue.pcapng and /dev/null differ diff --git a/wireshark_dumps/g910-spark/logo_g910.pcapng b/wireshark_dumps/g910-spark/logo_g910.pcapng deleted file mode 100755 index 2723709..0000000 Binary files a/wireshark_dumps/g910-spark/logo_g910.pcapng and /dev/null differ