From 793aa0d557a400757cd307fafe720444ca5e1a30 Mon Sep 17 00:00:00 2001 From: Kevin Pearson Date: Mon, 17 Apr 2017 12:37:57 -0400 Subject: [PATCH] Initial work to add G213 support Currently supported: - G213 by region {1..5} - Standard FX calls - Startup behavior - Help and command-line app support resolves MatMoul/g810-led#69 Signed-off-by: Kevin Pearson --- makefile | 2 + src/classes/Keyboard.cpp | 61 ++++++++++++++---- src/classes/Keyboard.h | 3 + src/helpers/help.cpp | 8 +++ src/main.cpp | 10 +++ .../g213-prodigy/DisableStartupEffect.pcapng | Bin 0 -> 520 bytes .../g213-prodigy/EnableStartupEffect.pcapng | Bin 0 -> 520 bytes .../g213-prodigy/Region1_E2-3F-5C.pcapng | Bin 0 -> 3112 bytes .../g213-prodigy/Region2_E2-3F-5C.pcapng | Bin 0 -> 3112 bytes .../g213-prodigy/Region3_E2-3F-5C.pcapng | Bin 0 -> 7432 bytes .../g213-prodigy/Region4_E2-3F-5C.pcapng | Bin 0 -> 7432 bytes .../g213-prodigy/Region5_E2-3F-5C.pcapng | Bin 0 -> 3112 bytes .../SetFX_FixedColor_E2-3F-5C.pcapng | Bin 0 -> 808 bytes 13 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 wireshark_dumps/g213-prodigy/DisableStartupEffect.pcapng create mode 100644 wireshark_dumps/g213-prodigy/EnableStartupEffect.pcapng create mode 100644 wireshark_dumps/g213-prodigy/Region1_E2-3F-5C.pcapng create mode 100644 wireshark_dumps/g213-prodigy/Region2_E2-3F-5C.pcapng create mode 100644 wireshark_dumps/g213-prodigy/Region3_E2-3F-5C.pcapng create mode 100644 wireshark_dumps/g213-prodigy/Region4_E2-3F-5C.pcapng create mode 100644 wireshark_dumps/g213-prodigy/Region5_E2-3F-5C.pcapng create mode 100644 wireshark_dumps/g213-prodigy/SetFX_FixedColor_E2-3F-5C.pcapng diff --git a/makefile b/makefile index 3b420a6..bef2777 100644 --- a/makefile +++ b/makefile @@ -55,6 +55,7 @@ setup: $(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/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 @@ -99,6 +100,7 @@ uninstall: systemctl daemon-reload && \ rm -R /etc/$(PROGN) + @rm /usr/bin/g213-led @rm /usr/bin/g410-led @rm /usr/bin/g610-led @rm /usr/bin/g910-led diff --git a/src/classes/Keyboard.cpp b/src/classes/Keyboard.cpp index 37a7fd8..7d02fff 100644 --- a/src/classes/Keyboard.cpp +++ b/src/classes/Keyboard.cpp @@ -231,6 +231,8 @@ LedKeyboard::KeyboardModel LedKeyboard::getKeyboardModel() { bool LedKeyboard::commit() { byte_buffer_t data; switch (m_keyboardModel) { + case KeyboardModel::g213: + break; // Keyboard is non-transactional case KeyboardModel::g410: case KeyboardModel::g610: case KeyboardModel::g810: @@ -430,17 +432,32 @@ bool LedKeyboard::setGroupKeys(KeyGroup keyGroup, LedKeyboard::Color color) { bool LedKeyboard::setAllKeys(LedKeyboard::Color color) { KeyValueArray keyValues; - for (uint8_t i = 0; i < keyGroupLogo.size(); i++) keyValues.push_back({keyGroupLogo[i], color}); - for (uint8_t i = 0; i < keyGroupIndicators.size(); i++) keyValues.push_back({keyGroupIndicators[i], color}); - for (uint8_t i = 0; i < keyGroupMultimedia.size(); i++) keyValues.push_back({keyGroupMultimedia[i], color}); - for (uint8_t i = 0; i < keyGroupGKeys.size(); i++) keyValues.push_back({keyGroupGKeys[i], color}); - for (uint8_t i = 0; i < keyGroupFKeys.size(); i++) keyValues.push_back({keyGroupFKeys[i], color}); - for (uint8_t i = 0; i < keyGroupFunctions.size(); i++) keyValues.push_back({keyGroupFunctions[i], color}); - for (uint8_t i = 0; i < keyGroupArrows.size(); i++) keyValues.push_back({keyGroupArrows[i], color}); - for (uint8_t i = 0; i < keyGroupNumeric.size(); i++) keyValues.push_back({keyGroupNumeric[i], color}); - for (uint8_t i = 0; i < keyGroupModifiers.size(); i++) keyValues.push_back({keyGroupModifiers[i], color}); - for (uint8_t i = 0; i < keyGroupKeys.size(); i++) keyValues.push_back({keyGroupKeys[i], color}); - return setKeys(keyValues); + + switch (m_keyboardModel) { + case KeyboardModel::g213: + for (uint8_t rIndex=0x01; rIndex <= 0x05; rIndex++) { + if (! setRegion(rIndex,color)) return false; + } + return true; + case KeyboardModel::g410: + case KeyboardModel::g610: + case KeyboardModel::g810: + case KeyboardModel::g910: + 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; } @@ -510,10 +527,25 @@ bool LedKeyboard::setGKeysMode(uint8_t value) { return false; } +bool LedKeyboard::setRegion(uint8_t region, LedKeyboard::Color color) { + LedKeyboard::byte_buffer_t data; + switch (m_keyboardModel) { + 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 (m_keyboardModel) { + case KeyboardModel::g213: case KeyboardModel::g410: case KeyboardModel::g610: case KeyboardModel::g810: @@ -535,6 +567,11 @@ bool LedKeyboard::setNativeEffect(NativeEffect effect, NativeEffectPart part, ui uint8_t protocolByte = 0; switch (m_keyboardModel) { + case KeyboardModel::g213: + protocolByte = 0x0c; + + if (part == NativeEffectPart::logo) return false; //Does not have logo component + break; case KeyboardModel::g410: case KeyboardModel::g610: // Unconfirmed case KeyboardModel::g810: @@ -653,6 +690,8 @@ bool LedKeyboard::sendDataInternal(byte_buffer_t &data) { LedKeyboard::byte_buffer_t LedKeyboard::getKeyGroupAddress(LedKeyboard::KeyAddressGroup keyAddressGroup) { switch (m_keyboardModel) { + case KeyboardModel::g213: + return {}; // Device doesn't support per-key setting case KeyboardModel::g410: case KeyboardModel::g610: case KeyboardModel::g810: diff --git a/src/classes/Keyboard.h b/src/classes/Keyboard.h index fdf7bbf..d99adda 100644 --- a/src/classes/Keyboard.h +++ b/src/classes/Keyboard.h @@ -17,6 +17,7 @@ class LedKeyboard { private: const std::vector> SupportedKeyboards = { + { 0x46d, 0xc336, (u_int16_t)KeyboardModel::g213 }, { 0x46d, 0xc330, (u_int16_t)KeyboardModel::g410 }, { 0x46d, 0xc333, (u_int16_t)KeyboardModel::g610 }, { 0x46d, 0xc338, (u_int16_t)KeyboardModel::g610 }, @@ -40,6 +41,7 @@ class LedKeyboard { enum class KeyboardModel : uint8_t { unknown = 0x00, + g213, g410, g610, g810, @@ -144,6 +146,7 @@ class LedKeyboard { 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); diff --git a/src/helpers/help.cpp b/src/helpers/help.cpp index cbcd74e..dffbd2f 100644 --- a/src/helpers/help.cpp +++ b/src/helpers/help.cpp @@ -19,6 +19,10 @@ namespace help { cout<<" -a {color}\t\t\t\tSet all keys color"< 2 && arg == "-an") return setAllKeys(kbd, argv[2], false); else if (argc > 3 && arg == "-gn") return setGroupKeys(kbd, argv[2], argv[3], false); else if (argc > 3 && arg == "-kn") return setKey(kbd, argv[2], argv[3], false); + else if (argc > 3 && arg == "-r") return setRegion(kbd, argv[2], argv[3]); else if (argc > 2 && arg == "-gkm") return setGKeysMode(kbd, argv[2]); diff --git a/wireshark_dumps/g213-prodigy/DisableStartupEffect.pcapng b/wireshark_dumps/g213-prodigy/DisableStartupEffect.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..6631133cc0fa721491079e0db0dc19ae1f34c216 GIT binary patch literal 520 zcmd<$<>jhiU|{gI(UxKa(*L1=nL&=h%tSXSvqT|0GcP5-yja1|Kt~~|G&3hf!O+Cm z(wKpPg+Z6Wr8Ku7Ik7-NBRsPxwKyZOC|gs(NY6;mOhKazOzRrxrW+fjBqp0BY68s% z0g!zly9$8#ClLSt&%nUMpurFmqZd<jhiU|{gI(UxKa(*L1=nL&=h%tSXSvqT|0GcP5-yja1|Kt~~|G&3hf!O+Cm z(wKpPg+Z6Wr8Ku7Ik7-NBRsPxwKyZOC|gs(NY6;mOhKazOzRrxrW+fjBqp0BY68s% z0g!zly9$8#ClLSt&%nUMpurFmqZd<|mSJcJdGNpaI>;Ri4ALOS@d91M z0pclg3NkS=h=BEi%m@Gp0s+Vj?iCxZ8vxlLjA{l410%!?5ug;K;D4T2kN`3OnFBJ< z1}X?L&j@Iq43H1O$Zmq02U5)h(u3}nC*B*c>jT9>SehZ>Rhm!>)IY$`0=cD$5#$zZ IP67J~03n%XeEHV%7>Cbk(vPT>8puRaWF!!YXi_^4sfa3-p#vEjv2}?^(+CwqgVR z0VY-$Kq_JY2L1qq)B%vXKqX)(od5wdWijuY#L0W{Ss0s>PWHLJ$FHCM&X@4mSa_2$ zHa~Obm;^_&(+1damdmD=^fh@wH>&lGRasRg<)wA~T2)rF+BuD}AWN~i_3Mr0N<&U8 z=*`;d71On(K@D-)QXm=R+e*>B=E7}^YB>>=!eivld%9xuu>^qYUqtx zX~SZbYny98FJ}~WTFI)@s;cJBY9lav5ax}#s1a^!JqPcf!vVBQ^C33*+9;lcbL?@p zTX->kXAkROEQZAep`u|NofwG(Bo=MWMaD(E2n`uiZ;YY>=h%71Fq7JhDEvu^n4@7h zat%4io9SFdo&vl$jN6^o)aBvb0i4rci}B7VPQi8TF}C<&(Y)PxAFzeB+>)>sEM>4I z9|l&lYN3Ag_ne>Yryl$q-Q)ZaM)!RzKY2+ym@NgYirSw0{Y(Il_!03CAoO$UGxejq zEJUsUcfX%}uZYf>$WP>e^Rso=gP$kB!0cd${1ArCkE{G3kN6Ss@Qs9iK7FTt{O9N6 z56+LL_4Vv0=Z7$Ce)6zL-Fl>HY z<>w0Uh#wKp(T@?V|JU!&P^eD7&)W|@_}K>rSzm-<^OGNNk)LnCBYs3YM?cy)_2WN3 zuYl)w|GFRH{D{_r^?i1gp9jDrendP+Kl?H2$N%@|W}Ndw_6qm=`-KV44`JBz6LgWE z0`Q0*5zo=jz0=f>|NN*4>gRm(ad$s-?1+^#$DzqM~JqVU62p%dPdZ{N5y1tiW=;PLv%GITL-84?&bCzt~x(co|_%iGwDn^uP3k7k0~Q{F`KEBr}O1ORd@hDzAieu^n zuzB#szMCJZ4uF0tE`$|DXm%vprz)V;?X1wV|@`aZ6of}(sqT~ghO8lKzzq>;z`$an;h`U$`0 zevDUVHTU;!_fz;=L~|tbvxYpDpF1mEszIUt8YM!mmczz!L7W}X*`}cF(5&SSlho3^oM}COM{K$Bo ze(Y$1{l5p#55y8YKi@xeu|MBO2EF@G$M+w`=&Oeb hzLpONeq`&Rwf}^D(I>)6W;3`}zO;`~hHG#1;Sm literal 0 HcmV?d00001 diff --git a/wireshark_dumps/g213-prodigy/Region3_E2-3F-5C.pcapng b/wireshark_dumps/g213-prodigy/Region3_E2-3F-5C.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..52b69f8224708aba7d4d41b34f00a34809a8047f GIT binary patch literal 7432 zcmeI1U2GIp6vxlZbo;Tkvel}ktuQEoMc8$Bww89O?$#D?4JavYFuK}qKfv{)-B6Hf zVgr<@U}Dq+UQA4^_++AuK7b@OYJ8Ad5<_T+9}h}Q#4H-44?-la=giI>?wy@Yhg~(O zy~*vlb7$`Vp8d@^bMH*uH8t*00NB{RvOz+dHHrd@przT@m)fCjNevAQ?;25qfmLeX z&eY=rYOp!f76K>(A9U?}BHf=%tKKcC?SmtaB)31dLe>15zeV*vsas#bw=JX%B>P*E zD^Q;b%|~;kv0lKM%>u~ag+#)iNT8Gkn3#&hmtvc06MSA3^XxlKegHI*b7kmJB^@oPs+A?E)5ns= zChEjO8si^C;sI<^6*VeB%4yW$DXBJF?M5pU(jmQeqnGp!prMTd|*NBlLdRn;kcP57HuE_DbXnxl*pf#{*WFFFc>ujthL+9xQ^-$h5$R(=dMz z;}e#oGm(VMJj!vl@_7#RI6iiIBw))YeTwH3_&8R_?zfds_>vPw%Z`tGR^W5|!y@>6 zff^J$R55-yjXXY%;^!jjaeVCb=oi`YS@I3fr}X$~|5o7h!)y_Ju0A91;WYC2gk=Zu zvlR6>K6ZKq`JB%1d`gd>qvr%Z+`V%C{F(Ss;KOO;@o^MC@1q{a$4;*xpO=2)`IH_% zW9J1v`@bt9eimO4_;4C|e8P%@_~}GFj*p#QK|V1h$~~V;j~}fp%CBFkJw@=Tc18K; z52umG$5H&;jCvd&JH3K@U;)pk^!RxT^|>Q{uOOf08qcS=_(_mD7TT*GoK3`Or$n_8CXY>+&z~yV zKf6Iz7UQY-<~uv-BzW)u+_wO%dHFK{eQQlUK$`kKPro3iok8tJJl3ndHtDU4ZCD!s z1>UL0w+Ac=npT|qEWKOc2A&lcHrlZ&MhDH*YqZJSg|!~*{zb1YeDTOhY5euWf@S?G zUSlogT*|X^0c_AKPOd2M05Lg?nHOg5by3 zkxu9^&eOcl8*SX>>90M1#k@C2-7pB-AO*uPgtPXb7aG3$g zZ)y_r-$OacSo2@I%=|BQ zUNQf*IrBe?{(23c0bF{T)AMy-a`Mzx_50fQD$h?J-PHHdZtN@mIUz%b^oE1ygz3n9 z<3B|}HuL|hRk>`Z{BFg1zs>r82liJOzrRraw_I~}DDvx!^iyVX;fBnN^mN}ZH@;GF zLb^D8UEk<4CnePw&zq}qiyYsjf6hspJ!R01ZCZzEeWq2>IuD!g+}%Gn(0puNeAigw zRDB$7nv^csiYsrczTVPGOY82CWxdT`7o)~_t1i(7TNGkMQVr=T6IBhtT{2%wg00X$ZO2Q3rKXEg`hb`D8B}uyA<=mk=Z-^9>!V{>JH5 z8KHzY(Gu|hE-r3k#t+21wQB*>6L%)^b5N^T>##5WG=azTrDo+eI{giMa?L#A_`Dpy zeXG{uE5~Q$JK8?CRFM8a09=PyC=|Rs^+gmj(ftPUXur~-JJjhs+p!7Q1Z)B}0h@qL zz$Rc5_#X*S&46kLdy5m!P3Eo^*obppj0( z*%U6uYiflsG5S=iZxm2{1Ap9z4tjR8(=7^+r;H_yCc2468t+|AVfs-|O|RhqjDCwf!@wsXTF9SU zsJF<+R4*l;&y}1{`uWpZrQ80dzV;AR>e*SEz z=X`iBTVG!Z)Udd|0vQ(aM+|a4JSL5INx=D$*7;m*Yf_jY4Z|y&!RvjOvVc-*3VMimy)l12z?F{F$^8EP)_5`mj literal 0 HcmV?d00001 diff --git a/wireshark_dumps/g213-prodigy/Region5_E2-3F-5C.pcapng b/wireshark_dumps/g213-prodigy/Region5_E2-3F-5C.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..d736fee8016b277dcf95155791255de2d099951d GIT binary patch literal 3112 zcmbu9&ui0Q7{}jq?O4l(oAjWrN<_g9*EUH@=fXhHdGIjsAgqV7ty{|${1w~H?VuMG ze;^`7J?q_xHx)dHo99_jrV~UF!9QRgoFMgi+Gc&;CV|)Hg@@!#^M3N=)9;&5Pfuux zF*Y`Gc#j0fYGZV;eJq`dO&jy_xN$yzVX-8u%Ah>GV4Tg%YAQLLWX#WEY;@tAIg>Nx z=(tfVl;(29GXt^~*Wzh8dZ~7dDY4n4me0+ka|6J~fzQKdnNV9$)hc5?7G>FNJZlmRWX#`>{2KXlZEv;Dz7pTxqowa7Sy7hxcyG*`|jaE`?@x|mdFgyAQtui71g zBR7zPyphIL5*Il?yPvk0m`~l~OWLezLp@*Cw z!m#-f%1;`2#E%ot)sOLr`thEh1CObnZ@VVi*kA8~(cE8@Ve_MR2;}D%@S1)cd9Hr; zKB0cR=V!+<^;02P7SGQQU^M+uhRu&qe*OTj>Bo`h>Sz5q_2WH1>n}Jz1E1RX{w%-b z{1ArCkM0-9&nobUA19uxpSvs6kN5l(RyjW#Z`#;jgKs%Mgkkd|l%He3BYvECu6|Ce sQ9s`E6M0Ad(7i6czczu<++UPo^P>j@@)N31KaMmN5dZ)H literal 0 HcmV?d00001 diff --git a/wireshark_dumps/g213-prodigy/SetFX_FixedColor_E2-3F-5C.pcapng b/wireshark_dumps/g213-prodigy/SetFX_FixedColor_E2-3F-5C.pcapng new file mode 100644 index 0000000000000000000000000000000000000000..f239f7b81e64a0b1a332c36a674fa30af0f3fa8e GIT binary patch literal 808 zcma)&%}&BV5XWbW5+Gn8;b4TAHSqw^Vp~dygv1LsLNs2uG{N$rHua<7!*cfQ3+TmH z@DY3h<1_dIo;}r>LQ5eWm}W9N+nwM3_n%0m5>o(Z)sOZVR(Bo|*auA&yXKg;&4>P@ zGvcyz%)1lwuFqw)d|C$B0udUMd%I`YywEm>gVC)qw2E9QDJ6{;p1dkb;!RoU8$Hb^ zBAI|l1q<0iau1cz`$yG(ERO2`u#ku4L8u6HS z51nsNgK^&4hIeK)4{=SIhwu3H>&qAE0LTGE@B<-6-9bDfFvxnd#JHeM3}RdgR#U;67yz(jQLn9(0Se zJTuZlQlg&u*!baV3H#%u!v3T`&49PLKe3&#KVe4j9^aoDu%9zs@DjKUbCDJ*)oI79!>=^5-8m<$})u literal 0 HcmV?d00001