Compare commits
10
Commits
qmk_sonix
...
release_0.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
405ff7f6a5 | ||
|
|
563ff31fe3 | ||
|
|
4a6c4f0e52 | ||
|
|
be838aa1d6 | ||
|
|
68b0287cdd | ||
|
|
d18f66f995 | ||
|
|
259ba898b0 | ||
|
|
d8252281ce | ||
|
|
a5928518c1 | ||
|
|
b3b392b3e2 |
+240
-9
@@ -16,6 +16,7 @@
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
|
||||
before_script:
|
||||
- echo "started by ${GITLAB_USER_NAME}"
|
||||
@@ -23,15 +24,15 @@ before_script:
|
||||
#reusable templates
|
||||
.ccache_init: &ccache_init
|
||||
before_script:
|
||||
- apt update
|
||||
- apt install -y build-essential qtcreator qtbase5-dev libusb-1.0-0-dev libhidapi-dev pkgconf wget git file
|
||||
- export QT_SELECT=qt5
|
||||
- export APPIMAGE_EXTRACT_AND_RUN=1
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Linux (AppImage) 32-bit Build Target #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 32 AppImage":
|
||||
<<: *ccache_init
|
||||
image: i386/debian:bullseye
|
||||
image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:stretch-32
|
||||
stage: build
|
||||
script:
|
||||
- export $(dpkg-architecture)
|
||||
@@ -50,7 +51,7 @@ before_script:
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 64 AppImage":
|
||||
<<: *ccache_init
|
||||
image: debian:bullseye
|
||||
image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:stretch-64
|
||||
stage: build
|
||||
script:
|
||||
- export $(dpkg-architecture)
|
||||
@@ -69,10 +70,9 @@ before_script:
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 32 deb":
|
||||
<<: *ccache_init
|
||||
image: i386/debian:bullseye
|
||||
image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:stretch-32
|
||||
stage: build
|
||||
script:
|
||||
- apt install -y debhelper
|
||||
- dpkg-architecture -l
|
||||
- dpkg-buildpackage --target-arch i386 -us -B
|
||||
- rm -v ../openrgb-dbgsym*.deb
|
||||
@@ -91,10 +91,9 @@ before_script:
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 64 deb":
|
||||
<<: *ccache_init
|
||||
image: debian:bullseye
|
||||
image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:stretch-64
|
||||
stage: build
|
||||
script:
|
||||
- apt install -y debhelper
|
||||
- dpkg-architecture -l
|
||||
- dpkg-buildpackage -us -B
|
||||
- rm -v ../openrgb-dbgsym*.deb
|
||||
@@ -134,7 +133,239 @@ before_script:
|
||||
paths:
|
||||
- openrgb*.rpm
|
||||
expire_in: 30 days
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Linux (.deb) Debian Bullseye 32-bit Build Target #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 32 deb Bullseye":
|
||||
<<: *ccache_init
|
||||
image: i386/debian:bullseye
|
||||
stage: build
|
||||
script:
|
||||
- apt update
|
||||
- apt install -y build-essential qtcreator qtbase5-dev libusb-1.0-0-dev libhidapi-dev pkgconf wget git file debhelper
|
||||
- dpkg-architecture -l
|
||||
- dpkg-buildpackage --target-arch i386 -us -B
|
||||
- rm -v ../openrgb-dbgsym*.deb
|
||||
- mv -v ../openrgb*.deb ./
|
||||
|
||||
artifacts:
|
||||
name: "${CI_PROJECT_NAME}_Linux_32_deb_${CI_COMMIT_SHORT_SHA}"
|
||||
paths:
|
||||
- openrgb*.deb
|
||||
exclude:
|
||||
- openrgb-dbgsym*.deb
|
||||
expire_in: 30 days
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Linux (.deb) Debian Bullseye 64-bit Build Target #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Linux 64 deb Bullseye":
|
||||
<<: *ccache_init
|
||||
image: debian:bullseye
|
||||
stage: build
|
||||
script:
|
||||
- apt update
|
||||
- apt install -y build-essential qtcreator qtbase5-dev libusb-1.0-0-dev libhidapi-dev pkgconf wget git file debhelper
|
||||
- dpkg-architecture -l
|
||||
- dpkg-buildpackage -us -B
|
||||
- rm -v ../openrgb-dbgsym*.deb
|
||||
- mv -v ../openrgb*.deb ./
|
||||
|
||||
artifacts:
|
||||
name: "${CI_PROJECT_NAME}_Linux_64_deb_${CI_COMMIT_SHORT_SHA}"
|
||||
paths:
|
||||
- openrgb*.deb
|
||||
exclude:
|
||||
- openrgb-dbgsym*.deb
|
||||
expire_in: 30 days
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Debian 32 Buster test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Debian 32 Buster":
|
||||
image: i386/debian:buster
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*i386.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 32 deb"
|
||||
needs:
|
||||
- "Linux 32 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Debian 32 Bullseye test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Debian 32 Bullseye":
|
||||
image: i386/debian:bullseye
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*i386.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 32 deb"
|
||||
needs:
|
||||
- "Linux 32 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Ubuntu 32 18.04LTS test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Ubuntu 32 18.04LTS":
|
||||
image: i386/ubuntu:bionic
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*i386.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 32 deb"
|
||||
needs:
|
||||
- "Linux 32 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Mint 32 19.3 test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Mint 32 20.1":
|
||||
image: linuxmintd/mint19.3-i386
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*i386.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 32 deb"
|
||||
needs:
|
||||
- "Linux 32 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Debian 64 Buster test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Debian 64 Buster":
|
||||
image: debian:buster
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Debian 64 Bullseye test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Debian 64 Bullseye":
|
||||
image: debian:bullseye
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Fedora 64 v34 test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Fedora 64 v34":
|
||||
image: fedora:34
|
||||
stage: test
|
||||
script:
|
||||
- yum -y localinstall ./openrgb*64.rpm
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- yum -y remove openrgb
|
||||
dependencies:
|
||||
- "Linux 64 rpm"
|
||||
needs:
|
||||
- "Linux 64 rpm"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Ubuntu 64 18.04LTS test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Ubuntu 64 18.04LTS":
|
||||
image: ubuntu:bionic
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Ubuntu 64 20.04LTS test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Ubuntu 64 20.04LTS":
|
||||
image: ubuntu:focal
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Ubuntu 64 20.10 test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Ubuntu 64 20.10":
|
||||
image: ubuntu:groovy
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Mint 64 20.1 test #
|
||||
#-----------------------------------------------------------------------#
|
||||
"Mint 64 20.1":
|
||||
image: linuxmintd/mint20.1-amd64
|
||||
stage: test
|
||||
script:
|
||||
- apt update
|
||||
- DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb
|
||||
- openrgb --version
|
||||
- openrgb -l
|
||||
- apt remove -y openrgb
|
||||
dependencies:
|
||||
- "Linux 64 deb"
|
||||
needs:
|
||||
- "Linux 64 deb"
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Windows (32-bit) Build Target #
|
||||
#-----------------------------------------------------------------------#
|
||||
|
||||
@@ -59,18 +59,18 @@ CorsairPeripheralController::CorsairPeripheralController(hid_device* dev_handle,
|
||||
ReadFirmwareInfo();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| K95 Platinum requires additional steps |
|
||||
| K55 and K95 Platinum require additional steps |
|
||||
\*-----------------------------------------------------*/
|
||||
if (logical_layout == CORSAIR_TYPE_K95_PLAT)
|
||||
if (logical_layout == CORSAIR_TYPE_K55 || logical_layout == CORSAIR_TYPE_K95_PLAT)
|
||||
{
|
||||
SpecialFunctionControl();
|
||||
}
|
||||
|
||||
LightingControl();
|
||||
|
||||
if (logical_layout == CORSAIR_TYPE_K95_PLAT)
|
||||
if (logical_layout == CORSAIR_TYPE_K55 || logical_layout == CORSAIR_TYPE_K95_PLAT)
|
||||
{
|
||||
SetupK95LightingControl();
|
||||
SetupK55AndK95LightingControl();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +232,6 @@ void CorsairPeripheralController::SetLEDsKeyboardFull(std::vector<RGBColor> colo
|
||||
SubmitKeyboardFullColors(3, 3, 2);
|
||||
}
|
||||
|
||||
|
||||
void CorsairPeripheralController::SetLEDsMouse(std::vector<RGBColor> colors)
|
||||
{
|
||||
SubmitMouseColors(colors.size(), &colors[0]);
|
||||
@@ -370,7 +369,7 @@ void CorsairPeripheralController::LightingControl()
|
||||
| Probably a key mapping packet? |
|
||||
\*-----------------------------------------------------*/
|
||||
|
||||
void CorsairPeripheralController::SetupK95LightingControl()
|
||||
void CorsairPeripheralController::SetupK55AndK95LightingControl()
|
||||
{
|
||||
char usb_buf[65];
|
||||
|
||||
@@ -535,7 +534,6 @@ void CorsairPeripheralController::ReadFirmwareInfo()
|
||||
|
||||
case 0x1B3D:
|
||||
logical_layout = CORSAIR_TYPE_K55;
|
||||
SpecialFunctionControl();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -97,7 +97,7 @@ private:
|
||||
int logical_layout; //Normal, K95 or K95 Platinum
|
||||
|
||||
void LightingControl();
|
||||
void SetupK95LightingControl();
|
||||
void SetupK55AndK95LightingControl();
|
||||
void SpecialFunctionControl();
|
||||
|
||||
void ReadFirmwareInfo();
|
||||
|
||||
@@ -91,7 +91,7 @@ void DetectCorsairPeripheralControllers(hid_device_info* info, const std::string
|
||||
/*-----------------------------------------------------------------------------------------------------*\
|
||||
| Keyboards |
|
||||
\*-----------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("Corsair K55 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K55_RGB_PID, 1, 0xFFC2); // Not per-key, disabled for now
|
||||
REGISTER_HID_DETECTOR_IP("Corsair K55 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K55_RGB_PID, 1, 0xFFC2);
|
||||
REGISTER_HID_DETECTOR_IP("Corsair K65 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K65_RGB_PID, 1, 0xFFC2);
|
||||
REGISTER_HID_DETECTOR_IP("Corsair K65 LUX RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K65_LUX_RGB_PID, 1, 0xFFC2);
|
||||
REGISTER_HID_DETECTOR_IP("Corsair K65 RGB RAPIDFIRE", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K65_RGB_RAPIDFIRE_PID, 1, 0xFFC2);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "Detector.h"
|
||||
#include "LogManager.h"
|
||||
#include "LogitechProtocolCommon.h"
|
||||
#include "LogitechG203LController.h"
|
||||
#include "LogitechG213Controller.h"
|
||||
#include "LogitechG560Controller.h"
|
||||
@@ -6,6 +8,7 @@
|
||||
#include "LogitechG910Controller.h"
|
||||
#include "LogitechG815Controller.h"
|
||||
#include "LogitechGLightsyncController.h"
|
||||
#include "LogitechLightspeedController.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_LogitechG203L.h"
|
||||
#include "RGBController_LogitechG213.h"
|
||||
@@ -15,10 +18,10 @@
|
||||
#include "RGBController_LogitechG815.h"
|
||||
#include "RGBController_LogitechGLightsync.h"
|
||||
#include "RGBController_LogitechGLightsync1zone.h"
|
||||
#include "RGBController_LogitechLightspeed.h"
|
||||
#include "RGBController_LogitechGPowerPlay.h"
|
||||
#include <vector>
|
||||
#include <hidapi/hidapi.h>
|
||||
#include <LogManager.h>
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Logitech vendor ID |
|
||||
@@ -44,27 +47,20 @@
|
||||
| Mouse product IDs |
|
||||
\*-----------------------------------------------------*/
|
||||
#define LOGITECH_G203_PID 0xC084
|
||||
#define LOGITECH_G203L_PID 0xC092
|
||||
#define LOGITECH_G203_LIGHTSYNC_PID 0xC092
|
||||
#define LOGITECH_G303_PID 0xC080
|
||||
#define LOGITECH_G403_PID 0xC083
|
||||
#define LOGITECH_G403H_PID 0xC08F
|
||||
#define LOGITECH_G403_WIRELESS_PID 0xC082
|
||||
#define LOGITECH_G403_WIRELESS_VIRTUAL_PID 0x405D
|
||||
#define LOGITECH_G502_PS_PID 0xC332
|
||||
#define LOGITECH_G502H_PID 0xC08B
|
||||
#define LOGITECH_G502_WIRELESS_PID 0xC08D
|
||||
#define LOGITECH_G502_WIRELESS_VIRTUAL_PID 0x407F
|
||||
#define LOGITECH_G703_WIRELESS_PID 0xC087
|
||||
#define LOGITECH_G703_WIRELESS_VIRTUAL_PID 0x4070
|
||||
#define LOGITECH_G900_WIRELESS_PID 0xC081
|
||||
#define LOGITECH_G900_WIRELESS_VIRTUAL_PID 0x4053
|
||||
#define LOGITECH_G903_WIRELESS_PID 0xC086
|
||||
#define LOGITECH_G903_WIRELESS_VIRTUAL_PID 0x4067
|
||||
#define LOGITECH_G_LIGHTSPEED_WIRELESS_PID 0xC539
|
||||
#define LOGITECH_GPRO_WIRED_PID 0xC085
|
||||
#define LOGITECH_GPRO_HERO_WIRED_PID 0xC08C
|
||||
#define LOGITECH_GPRO_WIRELESS_PID 0xC088
|
||||
#define LOGITECH_GPRO_WIRELESS_VIRTUAL_PID 0x4079
|
||||
#define LOGITECH_G403_HERO_PID 0xC08F
|
||||
#define LOGITECH_G403_LIGHTSPEED_PID 0xC082
|
||||
#define LOGITECH_G502_PROTEUS_SPECTRUM_PID 0xC332
|
||||
#define LOGITECH_G502_HERO_PID 0xC08B
|
||||
#define LOGITECH_G502_LIGHTSPEED_PID 0xC08D
|
||||
#define LOGITECH_G703_LIGHTSPEED_PID 0xC087
|
||||
#define LOGITECH_G900_LIGHTSPEED_PID 0xC081
|
||||
#define LOGITECH_G903_LIGHTSPEED_PID 0xC086
|
||||
#define LOGITECH_G_PRO_PID 0xC085
|
||||
#define LOGITECH_G_PRO_HERO_PID 0xC08C
|
||||
#define LOGITECH_G_PRO_WIRELESS_PID 0xC088
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Mousemat product IDs |
|
||||
@@ -76,6 +72,24 @@
|
||||
\*-----------------------------------------------------*/
|
||||
#define LOGITECH_G560_PID 0x0A78
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Unifying Device IDs (Including Lightspeed receivers) |
|
||||
| NB: Not used but preserved for debugging |
|
||||
\*-----------------------------------------------------*/
|
||||
#define LOGITECH_G_UNIFYING_RECEIVER_1_PID 0xC52B
|
||||
#define LOGITECH_G_NANO_RECEIVER_PID 0xC52F
|
||||
#define LOGITECH_G_G700_RECEIVER_PID 0xC531
|
||||
#define LOGITECH_G_UNIFYING_RECEIVER_2_PID 0xC532
|
||||
#define LOGITECH_G_G602_RECEIVER_PID 0xC537
|
||||
|
||||
#define LOGITECH_G_LIGHTSPEED_RECEIVER_PID 0xC539
|
||||
#define LOGITECH_G403_LIGHTSPEED_VIRTUAL_PID 0x405D
|
||||
#define LOGITECH_G502_LIGHTSPEED_VIRTUAL_PID 0x407F
|
||||
#define LOGITECH_G703_LIGHTSPEED_VIRTUAL_PID 0x4070
|
||||
#define LOGITECH_G900_LIGHTSPEED_VIRTUAL_PID 0x4053
|
||||
#define LOGITECH_G903_LIGHTSPEED_VIRTUAL_PID 0x4067
|
||||
#define LOGITECH_G_PRO_WIRELESS_VIRTUAL_PID 0x4079
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Logitech Keyboards |
|
||||
\*-----------------------------------------------------*/
|
||||
@@ -417,7 +431,6 @@ void DetectLogitechMouseG203L(hid_device_info* info, const std::string& name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DetectLogitechMouseG303(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0xFF, 0x0E, 0x3A);
|
||||
@@ -428,71 +441,11 @@ void DetectLogitechMouseG403(hid_device_info* info, const std::string& name)
|
||||
addLogitechLightsyncMouse2zone(info, name, 0xFF, 0x0E, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG403WW(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0xFF, 0x18, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG502PS(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0xFF, 0x02, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG502WW(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0xFF, 0x07, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG703WW(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0x01, 0x18, 0x3C);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG900WW(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0x01, 0x17, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseG903WW(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0x01, 0x17, 0x3A);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseGPRO(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
addLogitechLightsyncMouse2zone(info, name, 0x01, 0x07, 0x3C);
|
||||
}
|
||||
|
||||
void DetectLogitechMouseGLS(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
/*---------------------------------------------*\
|
||||
| Create mutex to prevent the two controllers |
|
||||
| from interfering with each other |
|
||||
\*---------------------------------------------*/
|
||||
std::shared_ptr<std::mutex> logitech_mutex = std::make_shared<std::mutex>();
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Add mouse |
|
||||
\*---------------------------------------------*/
|
||||
LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev, dev, info->path, 0x01, 0x07, 0x3C, logitech_mutex);
|
||||
RGBController_LogitechGLightsync* rgb_controller = new RGBController_LogitechGLightsync(controller);
|
||||
rgb_controller->name = name;
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
|
||||
/*---------------------------------------------*\
|
||||
| Add Powerplay mousemat |
|
||||
\*---------------------------------------------*/
|
||||
LogitechGLightsyncController* mousemat_controller = new LogitechGLightsyncController(dev, dev, info->path, 0x07, 0x0B, 0x3C, logitech_mutex);
|
||||
RGBController_LogitechGPowerPlay* mousemat_rgb_controller = new RGBController_LogitechGPowerPlay(mousemat_controller);
|
||||
mousemat_rgb_controller->name = name;
|
||||
ResourceManager::get()->RegisterRGBController(mousemat_rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Other Logitech Devices |
|
||||
\*-----------------------------------------------------*/
|
||||
@@ -529,27 +482,187 @@ REGISTER_HID_DETECTOR_IP ("Logitech G910 Orion Spectrum", Dete
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Mice |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G203 Prodigy", DetectLogitechMouseG203, LOGITECH_VID, LOGITECH_G203_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G203 Lightsync", DetectLogitechMouseG203L, LOGITECH_VID, LOGITECH_G203L_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G303 Daedalus Apex", DetectLogitechMouseG303, LOGITECH_VID, LOGITECH_G303_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G403 Prodigy", DetectLogitechMouseG403, LOGITECH_VID, LOGITECH_G403_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G403 Hero", DetectLogitechMouseG403, LOGITECH_VID, LOGITECH_G403H_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G403 Prodigy Wireless (wired)", DetectLogitechMouseG403WW, LOGITECH_VID, LOGITECH_G403_WIRELESS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 Proteus Spectrum", DetectLogitechMouseG502PS, LOGITECH_VID, LOGITECH_G502_PS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 Hero", DetectLogitechMouseG502PS, LOGITECH_VID, LOGITECH_G502H_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 LIGHTSPEED Wireless (wired)", DetectLogitechMouseG502WW, LOGITECH_VID, LOGITECH_G502_WIRELESS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G703 Wireless (wired)", DetectLogitechMouseG703WW, LOGITECH_VID, LOGITECH_G703_WIRELESS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G900 Chaos Spectrum Wireless (wired)", DetectLogitechMouseG900WW, LOGITECH_VID, LOGITECH_G900_WIRELESS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G903 LIGHTSPEED Wireless (wired)", DetectLogitechMouseG903WW, LOGITECH_VID, LOGITECH_G903_WIRELESS_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Pro Gaming Mouse", DetectLogitechMouseG203, LOGITECH_VID, LOGITECH_GPRO_WIRED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Pro (HERO) Gaming Mouse", DetectLogitechMouseG203, LOGITECH_VID, LOGITECH_GPRO_HERO_WIRED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Lightspeed Wireless Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_LIGHTSPEED_WIRELESS_PID, 2, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Pro Wireless Gaming Mouse (Wired)", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_GPRO_WIRELESS_PID, 2, 0xFF00);
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Mousemats |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G Powerplay Mousepad with Lightspeed", DetectLogitechMouseGLS, LOGITECH_VID, LOGITECH_G_LIGHTSPEED_POWERPLAY_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G203 Prodigy", DetectLogitechMouseG203, LOGITECH_VID, LOGITECH_G203_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G203 Lightsync", DetectLogitechMouseG203L, LOGITECH_VID, LOGITECH_G203_LIGHTSYNC_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G303 Daedalus Apex", DetectLogitechMouseG303, LOGITECH_VID, LOGITECH_G303_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G403 Hero", DetectLogitechMouseG403, LOGITECH_VID, LOGITECH_G403_HERO_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G Pro Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_PRO_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G Pro (HERO) Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_PRO_HERO_PID, 1, 0xFF00);
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Speakers |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G560 Lightsync Speaker", DetectLogitechG560, LOGITECH_VID, LOGITECH_G560_PID, 2, 0xFF43, 514);
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*\
|
||||
| Windows and MacOS Lightspeed Detection |
|
||||
| |
|
||||
| The Lightspeed receiver is a unifying receiver that will only accept 1 connection |
|
||||
| We must probe the receiver to check what is currently connected |
|
||||
| |
|
||||
| Hat tip - kernel driver https://github.com/torvalds/linux/blob/master/drivers/hid/hid-logitech-dj.c |
|
||||
| - ltunify https://github.com/Lekensteyn/ltunify/ |
|
||||
\*---------------------------------------------------------------------------------------------------------*/
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
|
||||
usages BundleLogitechUsages(hid_device_info* info)
|
||||
{
|
||||
usages temp_usages;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Need a unique ID to group usages for 1 device if multiple exist |
|
||||
| Grab all usages that you can open. For normal Logitech FAP |
|
||||
| devices this will be usage 1, 2 and 4 |
|
||||
\*-----------------------------------------------------------------*/
|
||||
if(info->usage == 1)
|
||||
{
|
||||
while(info)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
temp_usages.emplace((uint8_t)info->usage, dev);
|
||||
}
|
||||
|
||||
info = info->next;
|
||||
}
|
||||
}
|
||||
|
||||
return temp_usages;
|
||||
}
|
||||
|
||||
void CreateLogitechLightspeedDevice(char *path, usages device_usages, uint8_t device_index, bool wireless, std::shared_ptr<std::mutex> mutex_ptr)
|
||||
{
|
||||
LogitechLightspeedController* controller = new LogitechLightspeedController(device_usages.find(2)->second, path);
|
||||
controller->lightspeed = new logitech_device(path, device_usages, device_index, wireless, mutex_ptr);
|
||||
RGBController_LogitechLightspeed* rgb_controller = new RGBController_LogitechLightspeed(controller);
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
|
||||
void DetectLogitechLightspeedReceiver(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Need to save the PID and the device path before iterating |
|
||||
| over "info" in BundleLogitechUsages() |
|
||||
\*-----------------------------------------------------------------*/
|
||||
char *path = info->path;
|
||||
uint16_t dev_pid = info->product_id;
|
||||
usages device_usages = BundleLogitechUsages(info);
|
||||
|
||||
wireless_map wireless_devices;
|
||||
unsigned int device_count = getWirelessDevice(device_usages, dev_pid, &wireless_devices);
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Lightspeed Receivers will only have one paired /connected device |
|
||||
| Unifying Receivers can have up to 6 devices paired / connected |
|
||||
\*-----------------------------------------------------------------*/
|
||||
if(device_count > 0)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Create mutex to prevent the controllers sharing a |
|
||||
| receiver from interfering with each other |
|
||||
\*-------------------------------------------------*/
|
||||
std::shared_ptr<std::mutex> logitech_mutex = std::make_shared<std::mutex>();
|
||||
|
||||
for(wireless_map::iterator wd = wireless_devices.begin(); wd != wireless_devices.end(); wd++)
|
||||
{
|
||||
CreateLogitechLightspeedDevice(path, device_usages, wd->second, true, logitech_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DetectLogitechWired(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Need to save the device path before iterating |
|
||||
| over "info" in BundleLogitechUsages() |
|
||||
\*-----------------------------------------------------------------*/
|
||||
char *path = info->path;
|
||||
usages device_usages = BundleLogitechUsages(info);
|
||||
|
||||
if(device_usages.size() > 0)
|
||||
{
|
||||
CreateLogitechLightspeedDevice(path, device_usages, 0xFF, false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Lightspeed Receivers (Windows Wireless) |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("Logitech Lightspeed Receiver", DetectLogitechLightspeedReceiver, LOGITECH_VID, LOGITECH_G_LIGHTSPEED_RECEIVER_PID, 2, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Powerplay Mousepad", DetectLogitechLightspeedReceiver, LOGITECH_VID, LOGITECH_G_LIGHTSPEED_POWERPLAY_PID, 2, 0xFF00);
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Lightspeed Wireless Devices (Windows Wired) |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G403 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G403_LIGHTSPEED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_PROTEUS_SPECTRUM_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 Hero Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_HERO_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G502 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_LIGHTSPEED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G703 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G703_LIGHTSPEED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G900 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G900_LIGHTSPEED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G903 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("Logitech G Pro Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G_PRO_WIRELESS_PID, 2, 0xFF00);
|
||||
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------------------------------*\
|
||||
| Linux Lightspeed Detection |
|
||||
| |
|
||||
| The Linux kernel handles detecting wireless devices connected to a Unifying Receiver. |
|
||||
\*---------------------------------------------------------------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
|
||||
void CreateLogitechLightspeedDevice(hid_device_info* info, bool wireless)
|
||||
{
|
||||
usages device_usages;
|
||||
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
device_usages.emplace((uint8_t)info->usage, dev);
|
||||
}
|
||||
|
||||
if(device_usages.size() > 0)
|
||||
{
|
||||
LogitechLightspeedController* controller = new LogitechLightspeedController(device_usages.find(0)->second, info->path);
|
||||
controller->lightspeed = new logitech_device(info->path, device_usages, 0xFF, wireless);
|
||||
RGBController_LogitechLightspeed* rgb_controller = new RGBController_LogitechLightspeed(controller);
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectLogitechWireless(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
CreateLogitechLightspeedDevice(info, true);
|
||||
}
|
||||
|
||||
void DetectLogitechWired(hid_device_info* info, const std::string& /*name*/)
|
||||
{
|
||||
CreateLogitechLightspeedDevice(info, false);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Lightspeed Devices (Linux Wireless) |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G403 Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G403_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G502 Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G502_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G703 Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G703_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G900 Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G900_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G903 Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G Pro Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G_PRO_WIRELESS_VIRTUAL_PID, 2, 0xFF00, 2);
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------------------------------------------------------*\
|
||||
| Lightspeed Wireless Devices (Linux Wired) |
|
||||
\*-------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G403 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G403_LIGHTSPEED_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G502 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_PROTEUS_SPECTRUM_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G502 Hero Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_LIGHTSPEED_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G502 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_HERO_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G703 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G703_LIGHTSPEED_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G900 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G900_LIGHTSPEED_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G903 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_PID, 1, 0xFF00, 2);
|
||||
REGISTER_HID_DETECTOR_IPU("Logitech G Pro Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G_PRO_WIRELESS_PID, 2, 0xFF00, 2);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*-----------------------------------------*\
|
||||
| LogitechLightspeedController.cpp |
|
||||
| |
|
||||
| Driver for Logitech Lightspeed Wireless |
|
||||
| Gaming Mice lighting controller |
|
||||
| |
|
||||
| TheRogueZeta 8/5/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "LogitechLightspeedController.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
LogitechLightspeedController::LogitechLightspeedController(hid_device* dev_handle, const char* path)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
}
|
||||
|
||||
LogitechLightspeedController::~LogitechLightspeedController()
|
||||
{
|
||||
delete lightspeed;
|
||||
}
|
||||
|
||||
std::string LogitechLightspeedController::GetDeviceLocation()
|
||||
{
|
||||
return("HID: " + location + " (Receiver) \r\nWireless Index: " + std::to_string(lightspeed->device_index));
|
||||
}
|
||||
|
||||
std::string LogitechLightspeedController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
return(return_string);
|
||||
}
|
||||
|
||||
void LogitechLightspeedController::SendMouseMode
|
||||
(
|
||||
unsigned char mode,
|
||||
std::uint16_t speed,
|
||||
unsigned char zone,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue
|
||||
// unsigned char brightness
|
||||
)
|
||||
{
|
||||
lightspeed->setMode(mode, speed, zone, red, green, blue, 0x64);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*-----------------------------------------*\
|
||||
| LogitechLightspeedController.h |
|
||||
| |
|
||||
| Definitions and types for Logitech G |
|
||||
| Lightsync Wireless Gaming Mice lighting |
|
||||
| controller |
|
||||
| |
|
||||
| TheRogueZeta 8/5/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "LogitechProtocolCommon.h"
|
||||
|
||||
#include <string>
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
enum
|
||||
{
|
||||
LOGITECH_G_PRO_WIRELESS_MODE_OFF = 0x00,
|
||||
LOGITECH_G_PRO_WIRELESS_MODE_STATIC = 0x01,
|
||||
LOGITECH_G_PRO_WIRELESS_MODE_CYCLE = 0x02,
|
||||
LOGITECH_G_PRO_WIRELESS_MODE_BREATHING = 0x03,
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------------------*\
|
||||
| Speed is 1000 for fast and 20000 for slow. |
|
||||
| Values are multiplied by 100 later to give lots of GUI steps. |
|
||||
\*---------------------------------------------------------------------------------------------*/
|
||||
enum
|
||||
{
|
||||
LOGITECH_G_PRO_WIRELESS_SPEED_SLOWEST = 0xC8, /* Slowest speed */
|
||||
LOGITECH_G_PRO_WIRELESS_SPEED_NORMAL = 0x32, /* Normal speed */
|
||||
LOGITECH_G_PRO_WIRELESS_SPEED_FASTEST = 0x0A, /* Fastest speed */
|
||||
};
|
||||
|
||||
class LogitechLightspeedController
|
||||
{
|
||||
public:
|
||||
LogitechLightspeedController(hid_device* dev_handle, const char* path);
|
||||
~LogitechLightspeedController();
|
||||
|
||||
logitech_device* lightspeed;
|
||||
|
||||
std::string GetDeviceLocation();
|
||||
std::string GetSerialString();
|
||||
|
||||
void SendMouseMode
|
||||
(
|
||||
unsigned char mode,
|
||||
unsigned short speed,
|
||||
unsigned char zone,
|
||||
unsigned char red,
|
||||
unsigned char green,
|
||||
unsigned char blue
|
||||
// unsigned char brightness
|
||||
);
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::string location;
|
||||
};
|
||||
@@ -0,0 +1,587 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| LogitechProtocolCommon.cpp |
|
||||
| |
|
||||
| Common Logitech RAP and FAP protocol calls |
|
||||
| |
|
||||
| Chris M (Dr_No) 4th May 2021 |
|
||||
| |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include <LogitechProtocolCommon.h>
|
||||
|
||||
static std::vector<uint16_t> logitech_RGB_pages =
|
||||
{
|
||||
0x8070,
|
||||
0x8071
|
||||
};
|
||||
|
||||
int getWirelessDevice(usages device_usages, uint16_t pid, wireless_map *wireless_devices)
|
||||
{
|
||||
int result;
|
||||
hid_device* dev_use1;
|
||||
usages::iterator find_usage = device_usages.find(1);
|
||||
if (find_usage == device_usages.end())
|
||||
{
|
||||
LOG_NOTICE("Unable get_Wireless_Device due to missing FAP Short Message (0x10) usage");
|
||||
LOG_DEBUG("Dumping device usages:");
|
||||
for(usages::iterator dev = device_usages.begin(); dev != device_usages.end(); dev++)
|
||||
{
|
||||
LOG_DEBUG("Usage index:\t%i", dev->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_use1 = find_usage->second;
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
|
||||
shortFAPrequest get_connected_devices;
|
||||
get_connected_devices.init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
|
||||
|
||||
result = hid_write(dev_use1, get_connected_devices.buffer, get_connected_devices.size());
|
||||
result = hid_read_timeout(dev_use1, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
bool wireless_notifications = response.data[1] & 1; //Connected devices is a flag
|
||||
|
||||
if (!wireless_notifications)
|
||||
{
|
||||
response.init(); //zero out the response
|
||||
get_connected_devices.init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
|
||||
get_connected_devices.data[1] = 1;
|
||||
result = hid_write(dev_use1, get_connected_devices.buffer, get_connected_devices.size());
|
||||
result = hid_read_timeout(dev_use1, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
|
||||
if(get_connected_devices.feature_index == 0x8F)
|
||||
{
|
||||
LOG_ERROR("Logitech Protocol error: %02X %02X %02X %02X %02X %02X %02X", get_connected_devices.report_id, get_connected_devices.device_index, get_connected_devices.feature_index, get_connected_devices.feature_command, get_connected_devices.data[0], get_connected_devices.data[1], get_connected_devices.data[2]);
|
||||
}
|
||||
}
|
||||
|
||||
response.init(); //zero out the response
|
||||
get_connected_devices.init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_GET_REGISTER_REQUEST);
|
||||
get_connected_devices.feature_command = 0x02; //0x02 Connection State register. Essentially asking for count of paired devices
|
||||
result = hid_write(dev_use1, get_connected_devices.buffer, get_connected_devices.size());
|
||||
result = hid_read_timeout(dev_use1, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
|
||||
unsigned int device_count = response.data[1];
|
||||
LOG_NOTICE("Count of connected devices to %4X: %i", pid, device_count);
|
||||
|
||||
if (device_count > 0)
|
||||
{
|
||||
LOG_NOTICE("Faking a reconnect to get device list");
|
||||
device_count++; //Add 1 to the device_count to include the receiver
|
||||
|
||||
response.init();
|
||||
get_connected_devices.init(LOGITECH_RECEIVER_ADDRESS, LOGITECH_SET_REGISTER_REQUEST);
|
||||
get_connected_devices.feature_index = LOGITECH_SET_REGISTER_REQUEST;
|
||||
get_connected_devices.feature_command = 0x02; //0x02 Connection State register
|
||||
get_connected_devices.data[0] = 0x02; //Writting 0x02 to the connection state register will ask the receiver to fake a reconnect of paired devices
|
||||
result = hid_write(dev_use1, get_connected_devices.buffer, get_connected_devices.size());
|
||||
|
||||
for(size_t i = 0; i < device_count; i++)
|
||||
{
|
||||
blankFAPmessage devices;
|
||||
devices.init();
|
||||
|
||||
hid_read_timeout(dev_use1, devices.buffer, devices.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
unsigned int wireless_PID = (devices.data[2] << 8) | devices.data[1];
|
||||
LOG_NOTICE("Connected Device Index %i:\tVirtualID=%04X\t\t%02X %02X %02X %02X %02X %02X %02X", i, wireless_PID, devices.buffer[0], devices.buffer[1], devices.buffer[2], devices.buffer[3], devices.buffer[4], devices.buffer[5], devices.buffer[6]);
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| We need to read the receiver from the HID device queue but |
|
||||
| there is no need to add it as it's own device |
|
||||
\*-----------------------------------------------------------------*/
|
||||
if(devices.device_index != 0xFF)
|
||||
{
|
||||
wireless_devices->emplace(wireless_PID, devices.device_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_WARNING("No devices were found connected to receiver!");
|
||||
}
|
||||
}
|
||||
|
||||
return wireless_devices->size();
|
||||
}
|
||||
|
||||
logitech_device::logitech_device(char *path, usages _usages, uint8_t _device_index, bool _wireless)
|
||||
{
|
||||
device_index = _device_index;
|
||||
location = path;
|
||||
device_usages = _usages;
|
||||
wireless = _wireless;
|
||||
RGB_feature_index = 0;
|
||||
LED_count = 0;
|
||||
mutex = nullptr;
|
||||
|
||||
initialiseDevice();
|
||||
}
|
||||
|
||||
logitech_device::logitech_device(char *path, usages _usages, uint8_t _device_index, bool _wireless, std::shared_ptr<std::mutex> mutex_ptr)
|
||||
{
|
||||
device_index = _device_index;
|
||||
location = path;
|
||||
device_usages = _usages;
|
||||
wireless = _wireless;
|
||||
RGB_feature_index = 0;
|
||||
LED_count = 0;
|
||||
mutex = mutex_ptr;
|
||||
|
||||
initialiseDevice();
|
||||
}
|
||||
|
||||
logitech_device::~logitech_device()
|
||||
{
|
||||
for(usages::iterator dev = device_usages.begin(); dev != device_usages.end(); dev++)
|
||||
{
|
||||
hid_close(dev->second);
|
||||
}
|
||||
}
|
||||
|
||||
void logitech_device::initialiseDevice()
|
||||
{
|
||||
flushReadQueue();
|
||||
getDeviceName(); //This will get the name of the device if it exists
|
||||
|
||||
for(std::vector<uint16_t>::iterator page = logitech_RGB_pages.begin(); page != logitech_RGB_pages.end(); page++)
|
||||
{
|
||||
int feature_index = getFeatureIndex(*page);
|
||||
if(feature_index > 0)
|
||||
{
|
||||
feature_list.emplace(*page, feature_index);
|
||||
RGB_feature_index = feature_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (RGB_feature_index == 0)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| If there was no RGB Effect Feature page found |
|
||||
| dump the entire Feature list to log |
|
||||
\*-----------------------------------------------------------------*/
|
||||
getDeviceFeatureList(); //This will populate the feature list
|
||||
LOG_NOTICE("Unable add this device due to missing RGB Effects Feature");
|
||||
for(features::iterator feature = feature_list.begin(); feature != feature_list.end(); feature++)
|
||||
{
|
||||
LOG_NOTICE("Feature Index: %02X\tFeature Page: %04X", feature->second, feature->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getRGBconfig();
|
||||
}
|
||||
}
|
||||
|
||||
bool logitech_device::connected()
|
||||
{
|
||||
bool test = false;
|
||||
hid_device* dev_use1 = getDevice(1);
|
||||
|
||||
if(dev_use1)
|
||||
{
|
||||
blankFAPmessage response;
|
||||
response.init(); //zero out the response
|
||||
|
||||
shortFAPrequest get_connected_devices;
|
||||
get_connected_devices.init(device_index, LOGITECH_GET_REGISTER_REQUEST);
|
||||
get_connected_devices.feature_command = 0x02; //0x02 Connection State register. Essentially asking for count of paired devices
|
||||
hid_write(dev_use1, get_connected_devices.buffer, get_connected_devices.size());
|
||||
hid_read_timeout(dev_use1, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
test = (response.data[1] != 0x09); //ERR_RESOURCE_ERROR i.e. not currently connected
|
||||
}
|
||||
return test;
|
||||
}
|
||||
|
||||
uint8_t logitech_device::getLEDinfo()
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Get all info about the LEDs and Zones |
|
||||
\*-----------------------------------------------------------------*/
|
||||
|
||||
return LED_count;
|
||||
}
|
||||
|
||||
void logitech_device::flushReadQueue()
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
|
||||
for(usages::iterator dev = device_usages.begin(); dev != device_usages.end(); dev++)
|
||||
{
|
||||
//Flush the buffer
|
||||
int result = 1;
|
||||
while( result > 0 )
|
||||
{
|
||||
result = hid_read_timeout(dev->second, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hid_device* logitech_device::getDevice(uint8_t usage_index)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage_index |
|
||||
| Return the associated device if found otherwise a nullptr |
|
||||
\*-----------------------------------------------------------------*/
|
||||
#ifdef WIN32
|
||||
usages::iterator find_usage = device_usages.find(usage_index);
|
||||
#else
|
||||
usages::iterator find_usage = device_usages.begin();
|
||||
#endif //WIN32
|
||||
|
||||
if (find_usage == device_usages.end())
|
||||
{
|
||||
LOG_NOTICE("Unable add this device due to missing FAP Message usage %i", usage_index);
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return find_usage->second;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t logitech_device::getFeatureIndex(uint16_t feature_page)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Get the feature index from the Root Index |
|
||||
| Return the mapped feature_index of the given feature page |
|
||||
| for this device or else return 0 |
|
||||
\*-----------------------------------------------------------------*/
|
||||
int result = 0;
|
||||
uint8_t feature_index = 0;
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use2)
|
||||
{
|
||||
blankFAPmessage response;
|
||||
longFAPrequest get_index;
|
||||
get_index.init(device_index, LOGITECH_HIDPP_PAGE_ROOT_IDX, LOGITECH_CMD_ROOT_GET_FEATURE);
|
||||
get_index.data[0] = feature_page >> 8;
|
||||
get_index.data[1] = feature_page & 0xFF;
|
||||
|
||||
result = hid_write(dev_use2, get_index.buffer, get_index.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
feature_index = response.data[0];
|
||||
}
|
||||
return feature_index;
|
||||
}
|
||||
|
||||
int logitech_device::getDeviceFeatureList()
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage1 (0x10 Short FAP Message) & usage2 |
|
||||
| (0x11 Long FAP Message) then list all features for device |
|
||||
\*-----------------------------------------------------------------*/
|
||||
hid_device* dev_use1 = getDevice(1);
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use1 && dev_use2)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Query the root index for the index of the feature list |
|
||||
| This is done for safety as it is generaly at feature index 0x01 |
|
||||
\*-----------------------------------------------------------------*/
|
||||
shortFAPrequest get_index;
|
||||
get_index.init(device_index, LOGITECH_HIDPP_PAGE_ROOT_IDX);
|
||||
get_index.feature_command = LOGITECH_CMD_ROOT_GET_FEATURE;
|
||||
get_index.data[0] = LOGITECH_HIDPP_PAGE_FEATURE_SET >> 8; //Get feature index of the Feature Set 0x0001
|
||||
get_index.data[1] = LOGITECH_HIDPP_PAGE_FEATURE_SET & 0xFF;
|
||||
|
||||
result = hid_write(dev_use1, get_index.buffer, get_index.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
uint8_t feature_index = response.data[0];
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Get the count of Features |
|
||||
\*-----------------------------------------------------------------*/
|
||||
shortFAPrequest get_count;
|
||||
get_count.init(device_index, feature_index);
|
||||
get_count.feature_command = LOGITECH_CMD_FEATURE_SET_GET_COUNT;
|
||||
|
||||
result = hid_write(dev_use1, get_count.buffer, get_count.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
unsigned int feature_count = response.data[0];
|
||||
|
||||
shortFAPrequest get_features;
|
||||
get_features.init(device_index, feature_index);
|
||||
get_features.feature_command = LOGITECH_CMD_FEATURE_SET_GET_ID;
|
||||
for(std::size_t i = 1; feature_list.size() < feature_count; i++ )
|
||||
{
|
||||
get_features.data[0] = i;
|
||||
result = hid_write(dev_use1, get_features.buffer, get_features.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
LOG_DEBUG("Reading HID++ Feature %04X at index: %02X", (response.data[0] << 8) | response.data[1], i);
|
||||
feature_list.emplace((response.data[0] << 8) | response.data[1], i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!dev_use1)
|
||||
{
|
||||
LOG_NOTICE("Unable add this device due to missing FAP Short Message (0x10) usage");
|
||||
}
|
||||
if(!dev_use2)
|
||||
{
|
||||
LOG_NOTICE("Unable add this device due to missing FAP Long Message (0x11) usage");
|
||||
}
|
||||
}
|
||||
|
||||
return feature_list.size();
|
||||
}
|
||||
|
||||
int logitech_device::getDeviceName()
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage2 (0x11 Long FAP Message) |
|
||||
| Then use it to get the name for this device |
|
||||
\*-----------------------------------------------------------------*/
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use2)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
int result;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check if the feature_list contains an index for the Device_name |
|
||||
| feature otherwise query the root index. If not found return 0 |
|
||||
\*-----------------------------------------------------------------*/
|
||||
uint8_t name_feature_index;
|
||||
features::iterator find_feature = feature_list.find(LOGITECH_HIDPP_PAGE_DEVICE_NAME_TYPE);
|
||||
if (find_feature == feature_list.end())
|
||||
{
|
||||
longFAPrequest get_index;
|
||||
get_index.init(device_index, LOGITECH_HIDPP_PAGE_ROOT_IDX, LOGITECH_CMD_ROOT_GET_FEATURE);
|
||||
get_index.data[0] = LOGITECH_HIDPP_PAGE_DEVICE_NAME_TYPE >> 8; //Get feature index of the Feature Set 0x0001
|
||||
get_index.data[1] = LOGITECH_HIDPP_PAGE_DEVICE_NAME_TYPE & 0xFF;
|
||||
|
||||
result = hid_write(dev_use2, get_index.buffer, get_index.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
name_feature_index = response.data[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
name_feature_index = find_feature->second;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Get the device name length |
|
||||
\*-----------------------------------------------------------------*/
|
||||
longFAPrequest get_length;
|
||||
get_length.init(device_index, name_feature_index, LOTITECH_CMD_DEVICE_NAME_TYPE_GET_COUNT);
|
||||
result = hid_write(dev_use2, get_length.buffer, get_length.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
unsigned int name_length = response.data[0];
|
||||
|
||||
longFAPrequest get_name;
|
||||
get_name.init(device_index, name_feature_index, LOGITECH_CMD_DEVICE_NAME_TYPE_GET_DEVICE_NAME);
|
||||
while(device_name.length() < name_length)
|
||||
{
|
||||
get_name.data[0] = device_name.length(); //This sets the character index to get from the device
|
||||
result = hid_write(dev_use2, get_name.buffer, get_name.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
std::string temp = (char *)&response.data;
|
||||
device_name.append(temp);
|
||||
}
|
||||
|
||||
get_name.init(device_index, name_feature_index, LOGITECH_CMD_DEVICE_NAME_TYPE_GET_TYPE);
|
||||
result = hid_write(dev_use2, get_name.buffer, get_name.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
logitech_device_type = response.data[0];
|
||||
}
|
||||
|
||||
return device_name.length();
|
||||
}
|
||||
|
||||
void logitech_device::getRGBconfig()
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage2 (0x11 Long FAP Message) |
|
||||
| Then use it to get the name for this device |
|
||||
\*-----------------------------------------------------------------*/
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use2)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
int result;
|
||||
|
||||
longFAPrequest get_count;
|
||||
get_count.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_GET_COUNT);
|
||||
|
||||
result = hid_write(dev_use2, get_count.buffer, get_count.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
LED_count = response.data[0];
|
||||
|
||||
get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_INFO;
|
||||
for(std::size_t i = 0; i < LED_count; i++ )
|
||||
{
|
||||
//TODO: Push this info into a vector for later enumeration by the RGBController
|
||||
get_count.data[0] = i;
|
||||
result = hid_write(dev_use2, get_count.buffer, get_count.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
|
||||
/*get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_STATE;
|
||||
for(std::size_t i = 0; i < feature_count; i++ )
|
||||
{
|
||||
get_count.data[0] = i;
|
||||
result = hid_write(dev_use2, get_count.buffer, get_count.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
|
||||
get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_CONFIG;
|
||||
for(std::size_t i = 0; i < feature_count; i++ )
|
||||
{
|
||||
get_count.data[0] = i;
|
||||
result = hid_write(dev_use2, get_count.buffer, get_count.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t logitech_device::setDirectMode(bool direct)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage1 (0x10 Short FAP Message) & usage2 |
|
||||
| (0x11 Long FAP Message) then set the device into direct mode |
|
||||
| via register 0x8A |
|
||||
\*-----------------------------------------------------------------*/
|
||||
hid_device* dev_use1 = getDevice(1);
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use1 && dev_use2)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Turn the direct mode on or off via the RGB_feature_index |
|
||||
\*-----------------------------------------------------------------*/
|
||||
shortFAPrequest set_direct;
|
||||
set_direct.init(device_index, RGB_feature_index);
|
||||
set_direct.feature_command = LOGITECH_CMD_RGB_EFFECTS_UNKNOWN;
|
||||
set_direct.data[0] = (direct) ? 1 : 0;
|
||||
set_direct.data[1] = set_direct.data[0];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
| This code has to be protected to avoid crashes when |
|
||||
| this is called at the same time to change a powerplay |
|
||||
| mat and its paired wireless mouse leds. It will |
|
||||
| happen when using effects engines with high framerate |
|
||||
\*-----------------------------------------------------*/
|
||||
if(mutex)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(*mutex);
|
||||
|
||||
result = hid_write(dev_use1, set_direct.buffer, set_direct.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = hid_write(dev_use1, set_direct.buffer, set_direct.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Check the usage map for usage2 (0x11 Long FAP Message) then |
|
||||
| set the device mode via LOGITECH_CMD_RGB_EFFECTS_SET_CONTROL |
|
||||
\*-----------------------------------------------------------------*/
|
||||
hid_device* dev_use2 = getDevice(2);
|
||||
|
||||
if(dev_use2)
|
||||
{
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Create a buffer for reads |
|
||||
\*-----------------------------------------------------------------*/
|
||||
blankFAPmessage response;
|
||||
response.init();
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| Set the mode via the RGB_feature_index |
|
||||
\*-----------------------------------------------------------------*/
|
||||
longFAPrequest set_mode;
|
||||
set_mode.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_SET_CONTROL);
|
||||
set_mode.data[0] = zone;
|
||||
set_mode.data[1] = mode;
|
||||
|
||||
set_mode.data[2] = red;
|
||||
set_mode.data[3] = green;
|
||||
set_mode.data[4] = blue;
|
||||
|
||||
speed *= 100;
|
||||
if(mode == 1) //Static
|
||||
{
|
||||
set_mode.data[5] = zone;
|
||||
}
|
||||
else if(mode == 2) //Spectrum Cycle
|
||||
{
|
||||
set_mode.data[7] = speed >> 8;
|
||||
set_mode.data[8] = speed & 0xFF;
|
||||
set_mode.data[9] = brightness;
|
||||
}
|
||||
else if(mode == 3) //Breathing
|
||||
{
|
||||
set_mode.data[5] = speed >> 8;
|
||||
set_mode.data[6] = speed & 0xFF;
|
||||
set_mode.data[8] = brightness;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
| This code has to be protected to avoid crashes when |
|
||||
| this is called at the same time to change a powerplay |
|
||||
| mat and its paired wireless mouse leds. It will |
|
||||
| happen when using effects engines with high framerate |
|
||||
\*-----------------------------------------------------*/
|
||||
if(mutex)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(*mutex);
|
||||
|
||||
result = hid_write(dev_use2, set_mode.buffer, set_mode.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = hid_write(dev_use2, set_mode.buffer, set_mode.size());
|
||||
result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| LogitechProtocolCommon.h |
|
||||
| |
|
||||
| Common Logitech RAP and FAP protocol calls |
|
||||
| |
|
||||
| Chris M (Dr_No) 4th May 2021 |
|
||||
| |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include <map>
|
||||
#include <hidapi/hidapi.h>
|
||||
#include "LogManager.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LOGITECH_PROTOCOL_TIMEOUT 300 //Timeout in ms
|
||||
#define LOGITECH_HEADER_SIZE 3
|
||||
#define LOGITECH_SHORT_MESSAGE 0x10
|
||||
#define LOGITECH_SHORT_MESSAGE_LEN 7
|
||||
#define LOGITECH_LONG_MESSAGE 0x11
|
||||
#define LOGITECH_LONG_MESSAGE_LEN 20
|
||||
#define LOGITECH_FAP_RESPONSE_LEN 64 //Define a universal response buffer and allow the hidapi to determine the size
|
||||
|
||||
#define LOGITECH_RECEIVER_ADDRESS 0xFF //The Unifying receiver uses RAP or register access protocol
|
||||
#define LOGITECH_SET_REGISTER_REQUEST 0x80
|
||||
#define LOGITECH_GET_REGISTER_REQUEST 0x81
|
||||
|
||||
#define LOGITECH_HIDPP_PAGE_ROOT_IDX 0x00 //Used for querying the feature index
|
||||
#define LOGITECH_CMD_ROOT_GET_FEATURE 0x01
|
||||
#define LOGITECH_CMD_ROOT_GET_PROTOCOL 0x11
|
||||
|
||||
#define LOGITECH_HIDPP_PAGE_FEATURE_SET 0x0001
|
||||
#define LOGITECH_CMD_FEATURE_SET_GET_COUNT 0x01
|
||||
#define LOGITECH_CMD_FEATURE_SET_GET_ID 0x11
|
||||
|
||||
#define LOGITECH_HIDPP_PAGE_DEVICE_NAME_TYPE 0x0005
|
||||
#define LOTITECH_CMD_DEVICE_NAME_TYPE_GET_COUNT 0x01
|
||||
#define LOGITECH_CMD_DEVICE_NAME_TYPE_GET_DEVICE_NAME 0x11
|
||||
#define LOGITECH_CMD_DEVICE_NAME_TYPE_GET_TYPE 0x21
|
||||
|
||||
#define LOGITECH_HIDPP_PAGE_RGB_EFFECTS1 0x8070
|
||||
#define LOGITECH_HIDPP_PAGE_RGB_EFFECTS2 0x8071
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_GET_COUNT 0x00
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_GET_INFO 0x10
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_GET_CONTROL 0x20
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_SET_CONTROL 0x30
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_GET_STATE 0x40
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_SET_STATE 0x50
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_GET_CONFIG 0x60
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_SET_CONFIG 0x70
|
||||
#define LOGITECH_CMD_RGB_EFFECTS_UNKNOWN 0x80 //Used to set "direct" mode
|
||||
|
||||
enum LOGITECH_DEVICE_TYPE
|
||||
{
|
||||
LOGITECH_DEVICE_TYPE_KEYBOARD = 0,
|
||||
LOGITECH_DEVICE_TYPE_REMOTECONTROL =1,
|
||||
LOGITECH_DEVICE_TYPE_NUMPAD = 2,
|
||||
LOGITECH_DEVICE_TYPE_MOUSE = 3,
|
||||
LOGITECH_DEVICE_TYPE_TOUCHPAD = 4,
|
||||
LOGITECH_DEVICE_TYPE_TRACKBALL = 5,
|
||||
LOGITECH_DEVICE_TYPE_PRESENTER = 6,
|
||||
LOGITECH_DEVICE_TYPE_RECEIVER = 7
|
||||
};
|
||||
|
||||
// Used for: {GET,SET}_REGISTER_{REQ,RSP}, SET_LONG_REGISTER_RSP, GET_LONG_REGISTER_REQ
|
||||
struct message_short
|
||||
{
|
||||
unsigned char address;
|
||||
unsigned char data[3];
|
||||
};
|
||||
|
||||
// Used for: SET_LONG_REGISTER_REQ, GET_LONG_REGISTER_RSP
|
||||
struct message_long
|
||||
{
|
||||
unsigned char address;
|
||||
unsigned char data[16];
|
||||
};
|
||||
|
||||
// Used for: ERROR_MSG
|
||||
struct message_error
|
||||
{
|
||||
unsigned char sub_id;
|
||||
unsigned char address;
|
||||
unsigned char error_code;
|
||||
unsigned char padding; /* set to 0 */
|
||||
};
|
||||
|
||||
union shortFAPrequest
|
||||
{
|
||||
uint8_t buffer[LOGITECH_SHORT_MESSAGE_LEN];
|
||||
struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
uint8_t device_index;
|
||||
uint8_t feature_index;
|
||||
uint8_t feature_command;
|
||||
uint8_t data[LOGITECH_SHORT_MESSAGE_LEN - 4];
|
||||
};
|
||||
|
||||
void init(uint8_t device_index, uint8_t feature_index)
|
||||
{
|
||||
this->report_id = LOGITECH_SHORT_MESSAGE;
|
||||
this->device_index = device_index;
|
||||
this->feature_index = feature_index;
|
||||
this->feature_command = 0;
|
||||
for(size_t i = 0; i < sizeof(data); i++)
|
||||
{
|
||||
this->data[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
int size()
|
||||
{
|
||||
return LOGITECH_SHORT_MESSAGE_LEN;
|
||||
};
|
||||
};
|
||||
|
||||
union longFAPrequest
|
||||
{
|
||||
uint8_t buffer[LOGITECH_LONG_MESSAGE_LEN];
|
||||
struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
uint8_t device_index;
|
||||
uint8_t feature_index;
|
||||
uint8_t feature_command;
|
||||
uint8_t data[LOGITECH_LONG_MESSAGE_LEN - 4];
|
||||
};
|
||||
|
||||
void init(uint8_t device_index, uint8_t feature_index, uint8_t feature_command)
|
||||
{
|
||||
this->report_id = LOGITECH_LONG_MESSAGE;
|
||||
this->device_index = device_index;
|
||||
this->feature_index = feature_index;
|
||||
this->feature_command = feature_command;
|
||||
for(size_t i = 0; i < sizeof(data); i++)
|
||||
{
|
||||
this->data[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
int size()
|
||||
{
|
||||
return LOGITECH_LONG_MESSAGE_LEN;
|
||||
};
|
||||
};
|
||||
|
||||
union blankFAPmessage
|
||||
{
|
||||
uint8_t buffer[LOGITECH_FAP_RESPONSE_LEN];
|
||||
struct
|
||||
{
|
||||
uint8_t command;
|
||||
uint8_t device_index;
|
||||
uint8_t feature_index;
|
||||
uint8_t feature_command;
|
||||
uint8_t data[LOGITECH_FAP_RESPONSE_LEN - 4];
|
||||
};
|
||||
|
||||
//blank this buffer entirely
|
||||
void init()
|
||||
{
|
||||
for(size_t i = 0; i < sizeof(buffer); i++)
|
||||
{
|
||||
this->buffer[i] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
int size()
|
||||
{
|
||||
return LOGITECH_FAP_RESPONSE_LEN;
|
||||
};
|
||||
};
|
||||
|
||||
typedef std::map<uint8_t, hid_device*> usages;
|
||||
typedef std::map<uint16_t, uint8_t> features;
|
||||
typedef std::map<uint16_t, uint8_t> wireless_map;
|
||||
|
||||
int getWirelessDevice(usages _usages, uint16_t pid, wireless_map *wireless_devices); //Helper function needed outside of class
|
||||
|
||||
class logitech_device
|
||||
{
|
||||
public:
|
||||
logitech_device(char *path, usages _usages, uint8_t _device_index, bool _wireless);
|
||||
logitech_device(char *path, usages _usages, uint8_t _device_index, bool _wireless, std::shared_ptr<std::mutex> mutex_ptr);
|
||||
|
||||
~logitech_device();
|
||||
|
||||
/*-----------------------------------------------------------------*\
|
||||
| usages is a std::map that stores all the devices HID usages |
|
||||
| This is to ensure that we can communicate to all windows usages |
|
||||
\*-----------------------------------------------------------------*/
|
||||
usages device_usages;
|
||||
features feature_list;
|
||||
uint8_t device_index;
|
||||
uint8_t RGB_feature_index; //Stored for quick use
|
||||
uint8_t logitech_device_type;
|
||||
bool wireless;
|
||||
std::string device_name;
|
||||
std::string location;
|
||||
std::string protocol_version;
|
||||
|
||||
bool connected();
|
||||
void flushReadQueue();
|
||||
uint8_t getFeatureIndex(uint16_t feature_page);
|
||||
uint8_t getLEDinfo();
|
||||
uint8_t setDirectMode(bool direct);
|
||||
uint8_t setMode(uint8_t mode, uint16_t speed, uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness);
|
||||
int getDeviceName();
|
||||
private:
|
||||
uint8_t LED_count;
|
||||
std::shared_ptr<std::mutex> mutex;
|
||||
|
||||
hid_device* getDevice(uint8_t usage_index);
|
||||
int getDeviceFeatureList();
|
||||
void getRGBconfig();
|
||||
void initialiseDevice();
|
||||
};
|
||||
@@ -0,0 +1,177 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_LogitechLightspeed.cpp |
|
||||
| |
|
||||
| Generic RGB Interface for |
|
||||
| Logitech Lightspeed Gaming Mice |
|
||||
| |
|
||||
| TheRogueZeta 8/5/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "RGBController_LogitechLightspeed.h"
|
||||
|
||||
RGBController_LogitechLightspeed::RGBController_LogitechLightspeed(LogitechLightspeedController* logitech_ptr)
|
||||
{
|
||||
logitech = logitech_ptr;
|
||||
bool connected = logitech->lightspeed->connected();
|
||||
|
||||
mode Off;
|
||||
Off.name = "Off";
|
||||
Off.value = LOGITECH_G_PRO_WIRELESS_MODE_OFF;
|
||||
Off.flags = 0;
|
||||
Off.color_mode = MODE_COLORS_NONE;
|
||||
modes.push_back(Off);
|
||||
|
||||
if(connected)
|
||||
{
|
||||
name = logitech->lightspeed->device_name;
|
||||
vendor = "Logitech";
|
||||
description = "Logitech Wireless Lightspeed Device";
|
||||
location = logitech->GetDeviceLocation();
|
||||
serial = logitech->GetSerialString();
|
||||
|
||||
switch(logitech->lightspeed->logitech_device_type)
|
||||
{
|
||||
case LOGITECH_DEVICE_TYPE_KEYBOARD:
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
break;
|
||||
|
||||
case LOGITECH_DEVICE_TYPE_MOUSE:
|
||||
type = DEVICE_TYPE_MOUSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
type = DEVICE_TYPE_UNKNOWN;
|
||||
LOG_NOTICE("Logitech device type not known: %i", logitech->lightspeed->logitech_device_type);
|
||||
}
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0xFF;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
mode Static;
|
||||
Static.name = "Static";
|
||||
Static.value = LOGITECH_G_PRO_WIRELESS_MODE_STATIC;
|
||||
Static.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Static.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Static);
|
||||
|
||||
mode Cycle;
|
||||
Cycle.name = "Spectrum Cycle";
|
||||
Cycle.value = LOGITECH_G_PRO_WIRELESS_MODE_CYCLE;
|
||||
Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Cycle.color_mode = MODE_COLORS_NONE;
|
||||
Cycle.speed_min = LOGITECH_G_PRO_WIRELESS_SPEED_SLOWEST;
|
||||
Cycle.speed_max = LOGITECH_G_PRO_WIRELESS_SPEED_FASTEST;
|
||||
Cycle.speed = LOGITECH_G_PRO_WIRELESS_SPEED_NORMAL;
|
||||
modes.push_back(Cycle);
|
||||
|
||||
mode Breathing;
|
||||
Breathing.name = "Breathing";
|
||||
Breathing.value = LOGITECH_G_PRO_WIRELESS_MODE_BREATHING;
|
||||
Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS;
|
||||
Breathing.color_mode = MODE_COLORS_PER_LED;
|
||||
Breathing.speed_min = LOGITECH_G_PRO_WIRELESS_SPEED_SLOWEST;
|
||||
Breathing.speed_max = LOGITECH_G_PRO_WIRELESS_SPEED_FASTEST;
|
||||
Breathing.speed = LOGITECH_G_PRO_WIRELESS_SPEED_NORMAL;
|
||||
modes.push_back(Breathing);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "Idle Lightspeed Device";
|
||||
vendor = "Logitech";
|
||||
type = DEVICE_TYPE_UNKNOWN;
|
||||
description = "Idle Logitech Wireless Lightspeed Device";
|
||||
location = logitech->GetDeviceLocation();
|
||||
serial = logitech->GetSerialString();
|
||||
}
|
||||
}
|
||||
|
||||
RGBController_LogitechLightspeed::~RGBController_LogitechLightspeed()
|
||||
{
|
||||
delete logitech;
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::SetupZones()
|
||||
{
|
||||
uint8_t LED_count = logitech->lightspeed->getLEDinfo();
|
||||
|
||||
if(LED_count > 0)
|
||||
{
|
||||
for(size_t i = 0; i < LED_count; i++)
|
||||
{
|
||||
zone Lightspeed_logo_zone;
|
||||
Lightspeed_logo_zone.name = "Zone " + std::to_string(i);
|
||||
Lightspeed_logo_zone.type = ZONE_TYPE_SINGLE;
|
||||
Lightspeed_logo_zone.leds_min = 1;
|
||||
Lightspeed_logo_zone.leds_max = 1;
|
||||
Lightspeed_logo_zone.leds_count = 1;
|
||||
Lightspeed_logo_zone.matrix_map = NULL;
|
||||
zones.push_back(Lightspeed_logo_zone);
|
||||
|
||||
led Lightspeed_logo_led;
|
||||
Lightspeed_logo_led.name = "LED " + std::to_string(i);
|
||||
Lightspeed_logo_led.value = i;
|
||||
leds.push_back(Lightspeed_logo_led);
|
||||
}
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::DeviceUpdateLEDs()
|
||||
{
|
||||
for(std::vector<led>::iterator led_index = leds.begin(); led_index != leds.end(); led_index++)
|
||||
{
|
||||
UpdateZoneLEDs(led_index->value);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::UpdateZoneLEDs(int zone)
|
||||
{
|
||||
unsigned char red = RGBGetRValue(colors[zone]);
|
||||
unsigned char grn = RGBGetGValue(colors[zone]);
|
||||
unsigned char blu = RGBGetBValue(colors[zone]);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Replace direct mode with static when sending to controller|
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char temp_mode = (modes[active_mode].value == 0xFF) ? LOGITECH_G_PRO_WIRELESS_MODE_STATIC : modes[active_mode].value;
|
||||
|
||||
logitech->SendMouseMode(temp_mode, modes[active_mode].speed, zone, red, grn, blu);
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::UpdateSingleLED(int led)
|
||||
{
|
||||
UpdateZoneLEDs(led);
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::SetCustomMode()
|
||||
{
|
||||
if(logitech->lightspeed->connected())
|
||||
{
|
||||
active_mode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_LogitechLightspeed::DeviceUpdateMode()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| If direct mode is true, then sent the packet to put the |
|
||||
| mouse in direct mode. This code will only be called when |
|
||||
| we change modes as to not spam the device. |
|
||||
\*---------------------------------------------------------*/
|
||||
logitech->lightspeed->setDirectMode(modes[active_mode].value == 0xFF);
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_LogitechLightspeed.h |
|
||||
| |
|
||||
| Generic RGB Interface for |
|
||||
| Logitech Lightspeed Gaming Mice |
|
||||
| |
|
||||
| TheRogueZeta 8/5/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "RGBController.h"
|
||||
#include "LogitechLightspeedController.h"
|
||||
|
||||
class RGBController_LogitechLightspeed : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_LogitechLightspeed(LogitechLightspeedController* logitech_ptr);
|
||||
~RGBController_LogitechLightspeed();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void SetCustomMode();
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
LogitechLightspeedController* logitech;
|
||||
};
|
||||
@@ -0,0 +1,430 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| QMKOpenRGBController.cpp |
|
||||
| |
|
||||
| Driver for QMK keyboards using OpenRGB Protocol |
|
||||
| |
|
||||
| Kasper 10th Octobber 2020 |
|
||||
| Jath03 28th May 2021 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include "QMKOpenRGBController.h"
|
||||
|
||||
static std::map<uint8_t, std::string> QMKKeycodeToKeynameMap
|
||||
{
|
||||
{ 0, "" }, { 1, "Right Fn" }, { 2, "" }, { 3, "" },
|
||||
{ 4, "A" }, { 5, "B" }, { 6, "C" }, { 7, "D" },
|
||||
{ 8, "E" }, { 9, "F" }, { 10, "G" }, { 11, "H" },
|
||||
{ 12, "I" }, { 13, "J" }, { 14, "K" }, { 15, "L" },
|
||||
{ 16, "M" }, { 17, "N" }, { 18, "O" }, { 19, "P" },
|
||||
{ 20, "Q" }, { 21, "R" }, { 22, "S" }, { 23, "T" },
|
||||
{ 24, "U" }, { 25, "V" }, { 26, "W" }, { 27, "X" },
|
||||
{ 28, "Y" }, { 29, "Z" }, { 30, "1" }, { 31, "2" },
|
||||
{ 32, "3" }, { 33, "4" }, { 34, "5" }, { 35, "6" },
|
||||
{ 36, "7" }, { 37, "8" }, { 38, "9" }, { 39, "0" },
|
||||
{ 40, "Enter" }, { 41, "Escape" }, { 42, "Backspace" }, { 43, "Tab" },
|
||||
{ 44, "Space" }, { 45, "-" }, { 46, "=" }, { 47, "[" },
|
||||
{ 48, "]" }, { 49, "\\ (ANSI)" }, { 50, "" }, { 51, ";" },
|
||||
{ 52, "'" }, { 53, "`" }, { 54, "," }, { 55, "." },
|
||||
{ 56, "/" }, { 57, "Caps Lock" }, { 58, "F1" }, { 59, "F2" },
|
||||
{ 60, "F3" }, { 61, "F4" }, { 62, "F5" }, { 63, "F6" },
|
||||
{ 64, "F7" }, { 65, "F8" }, { 66, "F9" }, { 67, "F10" },
|
||||
{ 68, "F11" }, { 69, "F12" }, { 70, "Print Screen" }, { 71, "Scroll Lock" },
|
||||
{ 72, "Pause/Break" }, { 73, "Insert" }, { 74, "Home" }, { 75, "Page Up" },
|
||||
{ 76, "Delete" }, { 77, "End" }, { 78, "Page Down" }, { 79, "Right Arrow" },
|
||||
{ 80, "Left Arrow" }, { 81, "Down Arrow" }, { 82, "Up Arrow" }, { 83, "Num Lock" },
|
||||
{ 84, "Number Pad /" }, { 85, "Number Pad *" }, { 86, "Number Pad -" }, { 87, "Number Pad +" },
|
||||
{ 88, "Number Pad Enter" }, { 89, "Number Pad 1" }, { 90, "Number Pad 2" }, { 91, "Number Pad 3" },
|
||||
{ 92, "Number Pad 4" }, { 93, "Number Pad 5" }, { 94, "Number Pad 6" }, { 95, "Number Pad 7" },
|
||||
{ 96, "Number Pad 8" }, { 97, "Number Pad 9" }, { 98, "Number Pad 0" }, { 99, "Number Pad ." },
|
||||
{ 100, "" }, { 101, "Menu" }, { 102, "" }, { 103, "" },
|
||||
{ 104, "" }, { 105, "" }, { 106, "" }, { 107, "" },
|
||||
{ 108, "" }, { 109, "" }, { 110, "" }, { 111, "" },
|
||||
{ 112, "" }, { 113, "" }, { 114, "" }, { 115, "" },
|
||||
{ 116, "" }, { 117, "" }, { 118, "" }, { 119, "" },
|
||||
{ 120, "" }, { 121, "" }, { 122, "" }, { 123, "" },
|
||||
{ 124, "" }, { 125, "" }, { 126, "" }, { 127, "" },
|
||||
{ 128, "" }, { 129, "" }, { 130, "" }, { 131, "" },
|
||||
{ 132, "" }, { 133, "" }, { 134, "" }, { 135, "" },
|
||||
{ 136, "" }, { 137, "" }, { 138, "" }, { 139, "" },
|
||||
{ 140, "" }, { 141, "" }, { 142, "" }, { 143, "" },
|
||||
{ 144, "" }, { 145, "" }, { 146, "" }, { 147, "" },
|
||||
{ 148, "" }, { 149, "" }, { 150, "" }, { 151, "" },
|
||||
{ 152, "" }, { 153, "" }, { 154, "" }, { 155, "" },
|
||||
{ 156, "" }, { 157, "" }, { 158, "" }, { 159, "" },
|
||||
{ 160, "" }, { 161, "" }, { 162, "" }, { 163, "" }, { 164, "" },
|
||||
/*Space Cadet Left Shift*/ { 216, "Left Shift"}, /*Space Cadet Right Shift*/ { 217, "Right Shift"},
|
||||
{ 224, "Left Control" }, { 225, "Left Shift" }, { 226, "Left Alt" }, { 227, "Left Windows" },
|
||||
{ 228, "Right Control" }, { 229, "Right Shift" }, { 230, "Right Alt" }, { 231, "Right Windows" },
|
||||
};
|
||||
|
||||
QMKOpenRGBController::QMKOpenRGBController(hid_device *dev_handle, const char *path)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
|
||||
GetDeviceInfo();
|
||||
GetModeInfo();
|
||||
}
|
||||
|
||||
QMKOpenRGBController::~QMKOpenRGBController()
|
||||
{
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
std::string QMKOpenRGBController::GetLocation()
|
||||
{
|
||||
return location;
|
||||
}
|
||||
|
||||
std::string QMKOpenRGBController::GetDeviceName()
|
||||
{
|
||||
return device_name;
|
||||
}
|
||||
|
||||
std::string QMKOpenRGBController::GetDeviceVendor()
|
||||
{
|
||||
return device_vendor;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetTotalNumberOfLEDs()
|
||||
{
|
||||
return total_number_of_leds;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetTotalNumberOfLEDsWithEmptySpace()
|
||||
{
|
||||
return total_number_of_leds_with_empty_space;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetMode()
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetModeSpeed()
|
||||
{
|
||||
return mode_speed;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetModeColor()
|
||||
{
|
||||
return mode_color;
|
||||
}
|
||||
|
||||
std::vector<point_t> QMKOpenRGBController::GetLEDPoints()
|
||||
{
|
||||
return led_points;
|
||||
}
|
||||
|
||||
std::vector<unsigned int> QMKOpenRGBController::GetLEDFlags()
|
||||
{
|
||||
return led_flags;
|
||||
}
|
||||
|
||||
std::vector<std::string> QMKOpenRGBController::GetLEDNames()
|
||||
{
|
||||
return led_names;
|
||||
}
|
||||
|
||||
std::vector<RGBColor> QMKOpenRGBController::GetLEDColors()
|
||||
{
|
||||
return led_colors;
|
||||
}
|
||||
|
||||
unsigned int QMKOpenRGBController::GetProtocolVersion()
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_PROTOCOL_VERSION;
|
||||
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
hid_write(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
bytes_read = hid_read_timeout(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE, QMK_HID_READ_TIMEOUT);
|
||||
} while(bytes_read <= 0);
|
||||
|
||||
return usb_buf[1];
|
||||
}
|
||||
|
||||
std::string QMKOpenRGBController::GetQMKVersion()
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_QMK_VERSION;
|
||||
|
||||
hid_write(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
hid_read(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
std::string qmk_version;
|
||||
int i = 1;
|
||||
while (usb_buf[i] != 0)
|
||||
{
|
||||
qmk_version.push_back(usb_buf[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
return qmk_version;
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::GetDeviceInfo()
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_DEVICE_INFO;
|
||||
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
hid_write(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
bytes_read = hid_read_timeout(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE, QMK_HID_READ_TIMEOUT);
|
||||
} while(bytes_read <= 0);
|
||||
|
||||
total_number_of_leds = usb_buf[QMK_OPENRGB_TOTAL_NUMBER_OF_LEDS_BYTE];
|
||||
total_number_of_leds_with_empty_space = usb_buf[QMK_OPENRGB_TOTAL_NUMBER_OF_LEDS_WITH_EMPTY_SPACE_BYTE];
|
||||
|
||||
int i = QMK_OPENRGB_TOTAL_NUMBER_OF_LEDS_WITH_EMPTY_SPACE_BYTE + 1;
|
||||
while (usb_buf[i] != 0)
|
||||
{
|
||||
device_name.push_back(usb_buf[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
i++;
|
||||
while (usb_buf[i] != 0)
|
||||
{
|
||||
device_vendor.push_back(usb_buf[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::GetModeInfo()
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_MODE_INFO;
|
||||
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
hid_write(dev, usb_buf, 65);
|
||||
bytes_read = hid_read_timeout(dev, usb_buf, 65, QMK_HID_READ_TIMEOUT);
|
||||
} while(bytes_read <= 0);
|
||||
|
||||
mode = usb_buf[QMK_OPENRGB_MODE_BYTE];
|
||||
mode_speed = usb_buf[QMK_OPENRGB_SPEED_BYTE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| QMK hue range is between 0-255 so hue needs to be |
|
||||
| converted |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned int oldRange = 255;
|
||||
unsigned int newRange = 359;
|
||||
unsigned int convertedHue = (usb_buf[QMK_OPENRGB_HUE_BYTE] * newRange / oldRange);
|
||||
|
||||
hsv_t hsv;
|
||||
hsv.hue = convertedHue;
|
||||
hsv.saturation = usb_buf[QMK_OPENRGB_SATURATION_BYTE];
|
||||
hsv.value = usb_buf[QMK_OPENRGB_VALUE_BYTE];
|
||||
|
||||
mode_color = hsv2rgb(&hsv);
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::GetLEDInfo(unsigned int led)
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_LED_INFO;
|
||||
usb_buf[0x02] = led;
|
||||
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
hid_write(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
bytes_read = hid_read_timeout(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE, QMK_HID_READ_TIMEOUT);
|
||||
} while(bytes_read <= 0);
|
||||
|
||||
if(usb_buf[62] != QMK_OPENRGB_FAILURE)
|
||||
{
|
||||
led_points.push_back(point_t{usb_buf[QMK_OPENRGB_POINT_X_BYTE], usb_buf[QMK_OPENRGB_POINT_Y_BYTE]});
|
||||
led_flags.push_back(usb_buf[QMK_OPENRGB_FLAG_BYTE]);
|
||||
led_colors.push_back(ToRGBColor(usb_buf[QMK_OPENRGB_R_COLOR_BYTE], usb_buf[QMK_OPENRGB_G_COLOR_BYTE], usb_buf[QMK_OPENRGB_B_COLOR_BYTE]));
|
||||
}
|
||||
|
||||
if(usb_buf[QMK_OPENRGB_KEYCODE_BYTE] != 0)
|
||||
{
|
||||
if (QMKKeycodeToKeynameMap.count(usb_buf[QMK_OPENRGB_KEYCODE_BYTE]) > 0)
|
||||
{
|
||||
led_names.push_back("Key: " + QMKKeycodeToKeynameMap[usb_buf[QMK_OPENRGB_KEYCODE_BYTE]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
led_names.push_back("Key: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QMKOpenRGBController::GetIsModeEnabled(unsigned int mode)
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_GET_IS_MODE_ENABLED;
|
||||
usb_buf[0x02] = mode;
|
||||
|
||||
int bytes_read = 0;
|
||||
do
|
||||
{
|
||||
hid_write(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE);
|
||||
bytes_read = hid_read_timeout(dev, usb_buf, QMK_OPENRGB_PACKET_SIZE, QMK_HID_READ_TIMEOUT);
|
||||
} while(bytes_read <= 0);
|
||||
|
||||
return usb_buf[1] == QMK_OPENRGB_SUCCESS ? true : false;
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed)
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_SET_MODE;
|
||||
usb_buf[0x02] = hsv_color.hue * 255 / 359;
|
||||
usb_buf[0x03] = hsv_color.saturation;
|
||||
usb_buf[0x04] = hsv_color.value;
|
||||
usb_buf[0x05] = mode;
|
||||
usb_buf[0x06] = speed;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, 65);
|
||||
hid_read_timeout(dev, usb_buf, 65, QMK_HID_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue)
|
||||
{
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_DIRECT_MODE_SET_SINGLE_LED;
|
||||
usb_buf[0x02] = led;
|
||||
usb_buf[0x03] = red;
|
||||
usb_buf[0x04] = green;
|
||||
usb_buf[0x05] = blue;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Send packet |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_write(dev, usb_buf, 65);
|
||||
hid_read_timeout(dev, usb_buf, 65, QMK_HID_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
void QMKOpenRGBController::DirectModeSetLEDs(std::vector<RGBColor> colors, unsigned int leds_count)
|
||||
{
|
||||
unsigned int leds_sent = 0;
|
||||
unsigned int leds_per_update = 20;
|
||||
|
||||
while (leds_sent < leds_count)
|
||||
{
|
||||
if ((leds_count - leds_sent) < leds_per_update)
|
||||
{
|
||||
leds_per_update = leds_count - leds_sent;
|
||||
}
|
||||
|
||||
unsigned char usb_buf[QMK_OPENRGB_PACKET_SIZE];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, QMK_OPENRGB_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up config table request packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0x00] = 0x00;
|
||||
usb_buf[0x01] = QMK_OPENRGB_DIRECT_MODE_SET_LEDS;
|
||||
usb_buf[0x02] = leds_sent;
|
||||
usb_buf[0x03] = leds_per_update;
|
||||
|
||||
for (unsigned int led_idx = 0; led_idx < leds_per_update; led_idx++)
|
||||
{
|
||||
usb_buf[(led_idx * 3) + 4] = RGBGetRValue(colors[led_idx + leds_sent]);
|
||||
usb_buf[(led_idx * 3) + 5] = RGBGetGValue(colors[led_idx + leds_sent]);
|
||||
usb_buf[(led_idx * 3) + 6] = RGBGetBValue(colors[led_idx + leds_sent]);
|
||||
}
|
||||
|
||||
hid_write(dev, usb_buf, 65);
|
||||
|
||||
leds_sent += leds_per_update;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| QMKOpenRGBController.h |
|
||||
| |
|
||||
| Driver for QMK keyboards using OpenRGB Protocol |
|
||||
| |
|
||||
| Kasper 10th Octobber 2020 |
|
||||
| Jath03 28th May 2021 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "hsv.h"
|
||||
#include <hidapi/hidapi.h>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
|
||||
#define QMK_OPENRGB_PACKET_SIZE 65
|
||||
#define QMK_HID_READ_TIMEOUT 50
|
||||
|
||||
enum CommandsId
|
||||
{
|
||||
QMK_OPENRGB_GET_PROTOCOL_VERSION = 1,
|
||||
QMK_OPENRGB_GET_QMK_VERSION,
|
||||
QMK_OPENRGB_GET_DEVICE_INFO,
|
||||
QMK_OPENRGB_GET_MODE_INFO,
|
||||
QMK_OPENRGB_GET_LED_INFO,
|
||||
QMK_OPENRGB_GET_IS_MODE_ENABLED,
|
||||
|
||||
QMK_OPENRGB_SET_MODE,
|
||||
QMK_OPENRGB_DIRECT_MODE_SET_SINGLE_LED,
|
||||
QMK_OPENRGB_DIRECT_MODE_SET_LEDS,
|
||||
};
|
||||
|
||||
enum Modes
|
||||
{
|
||||
QMK_OPENRGB_MODE_OPENRGB_DIRECT = 1,
|
||||
QMK_OPENRGB_MODE_SOLID_COLOR,
|
||||
QMK_OPENRGB_MODE_ALPHA_MOD,
|
||||
QMK_OPENRGB_MODE_GRADIENT_UP_DOWN,
|
||||
QMK_OPENRGB_MODE_GRADIENT_LEFT_RIGHT,
|
||||
QMK_OPENRGB_MODE_BREATHING,
|
||||
QMK_OPENRGB_MODE_BAND_SAT,
|
||||
QMK_OPENRGB_MODE_BAND_VAL,
|
||||
QMK_OPENRGB_MODE_BAND_PINWHEEL_SAT,
|
||||
QMK_OPENRGB_MODE_BAND_PINWHEEL_VAL,
|
||||
QMK_OPENRGB_MODE_BAND_SPIRAL_SAT,
|
||||
QMK_OPENRGB_MODE_BAND_SPIRAL_VAL,
|
||||
QMK_OPENRGB_MODE_CYCLE_ALL,
|
||||
QMK_OPENRGB_MODE_CYCLE_LEFT_RIGHT,
|
||||
QMK_OPENRGB_MODE_CYCLE_UP_DOWN,
|
||||
QMK_OPENRGB_MODE_CYCLE_OUT_IN,
|
||||
QMK_OPENRGB_MODE_CYCLE_OUT_IN_DUAL,
|
||||
QMK_OPENRGB_MODE_RAINBOW_MOVING_CHEVRON,
|
||||
QMK_OPENRGB_MODE_CYCLE_PINWHEEL,
|
||||
QMK_OPENRGB_MODE_CYCLE_SPIRAL,
|
||||
QMK_OPENRGB_MODE_DUAL_BEACON,
|
||||
QMK_OPENRGB_MODE_RAINBOW_BEACON,
|
||||
QMK_OPENRGB_MODE_RAINBOW_PINWHEELS,
|
||||
QMK_OPENRGB_MODE_RAINDROPS,
|
||||
QMK_OPENRGB_MODE_JELLYBEAN_RAINDROPS,
|
||||
QMK_OPENRGB_MODE_HUE_BREATHING,
|
||||
QMK_OPENRGB_MODE_HUE_PENDULUM,
|
||||
QMK_OPENRGB_MODE_HUE_WAVE,
|
||||
QMK_OPENRGB_MODE_TYPING_HEATMAP,
|
||||
QMK_OPENRGB_MODE_DIGITAL_RAIN,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_SIMPLE,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_WIDE,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTIWIDE,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_CROSS,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTICROSS,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_NEXUS,
|
||||
QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTINEXUS,
|
||||
QMK_OPENRGB_MODE_SPLASH,
|
||||
QMK_OPENRGB_MODE_MULTISPLASH,
|
||||
QMK_OPENRGB_MODE_SOLID_SPLASH,
|
||||
QMK_OPENRGB_MODE_SOLID_MULTISPLASH,
|
||||
};
|
||||
|
||||
enum SpeedCommands
|
||||
{
|
||||
QMK_OPENRGB_SPEED_SLOWEST = 0x00, /* Slowest speed */
|
||||
QMK_OPENRGB_SPEED_NORMAL = 0x7F, /* Normal speed */
|
||||
QMK_OPENRGB_SPEED_FASTEST = 0xFF, /* Fastest speed */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QMK_OPENRGB_FAILURE = 25, /* Failure status code */
|
||||
QMK_OPENRGB_SUCCESS = 50, /* Success status code */
|
||||
QMK_OPENRGB_END_OF_MESSAGE = 100, /* End of Message status code */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QMK_OPENRGB_TOTAL_NUMBER_OF_LEDS_BYTE = 1,
|
||||
QMK_OPENRGB_TOTAL_NUMBER_OF_LEDS_WITH_EMPTY_SPACE_BYTE = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QMK_OPENRGB_MODE_BYTE = 1,
|
||||
QMK_OPENRGB_SPEED_BYTE = 2,
|
||||
QMK_OPENRGB_HUE_BYTE = 3,
|
||||
QMK_OPENRGB_SATURATION_BYTE = 4,
|
||||
QMK_OPENRGB_VALUE_BYTE = 5,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
QMK_OPENRGB_POINT_X_BYTE = 1,
|
||||
QMK_OPENRGB_POINT_Y_BYTE = 2,
|
||||
QMK_OPENRGB_FLAG_BYTE = 3,
|
||||
QMK_OPENRGB_R_COLOR_BYTE = 4,
|
||||
QMK_OPENRGB_G_COLOR_BYTE = 5,
|
||||
QMK_OPENRGB_B_COLOR_BYTE = 6,
|
||||
QMK_OPENRGB_KEYCODE_BYTE = 7
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
} point_t;
|
||||
|
||||
class QMKOpenRGBController
|
||||
{
|
||||
public:
|
||||
QMKOpenRGBController(hid_device *dev_handle, const char *path);
|
||||
~QMKOpenRGBController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetDeviceName();
|
||||
std::string GetDeviceVendor();
|
||||
|
||||
unsigned int GetTotalNumberOfLEDs();
|
||||
unsigned int GetTotalNumberOfLEDsWithEmptySpace();
|
||||
unsigned int GetMode();
|
||||
unsigned int GetModeSpeed();
|
||||
unsigned int GetModeColor();
|
||||
|
||||
std::vector<point_t> GetLEDPoints();
|
||||
std::vector<unsigned int> GetLEDFlags();
|
||||
std::vector<std::string> GetLEDNames();
|
||||
std::vector<RGBColor> GetLEDColors();
|
||||
|
||||
unsigned int GetProtocolVersion();
|
||||
std::string GetQMKVersion();
|
||||
void GetDeviceInfo();
|
||||
void GetModeInfo();
|
||||
void GetLEDInfo(unsigned int led);
|
||||
bool GetIsModeEnabled(unsigned int mode);
|
||||
|
||||
void SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed);
|
||||
void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue);
|
||||
void DirectModeSetLEDs(std::vector<RGBColor> colors, unsigned int num_colors);
|
||||
|
||||
protected:
|
||||
hid_device *dev;
|
||||
|
||||
private:
|
||||
std::string location;
|
||||
|
||||
std::string device_name;
|
||||
std::string device_vendor;
|
||||
|
||||
unsigned int total_number_of_leds;
|
||||
unsigned int total_number_of_leds_with_empty_space;
|
||||
unsigned int mode;
|
||||
unsigned int mode_speed;
|
||||
|
||||
RGBColor mode_color;
|
||||
|
||||
std::vector<point_t> led_points;
|
||||
std::vector<unsigned int> led_flags;
|
||||
std::vector<std::string> led_names;
|
||||
std::vector<RGBColor> led_colors;
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| QMKOpenRGBControllerDetect.cpp |
|
||||
| |
|
||||
| Driver for QMK keyboards using OpenRGB Protocol |
|
||||
| |
|
||||
| Kasper 10th Octobber 2020 |
|
||||
| Jath03 28th May 2021 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "Detector.h"
|
||||
#include "QMKOpenRGBController.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_QMKOpenRGB.h"
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Protocol version |
|
||||
\*-----------------------------------------------------*/
|
||||
#define QMK_OPENRGB_PROTOCOL_VERSION 0x09
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Usage and Usage Page |
|
||||
\*-----------------------------------------------------*/
|
||||
#define QMK_USAGE_PAGE 0xFF60
|
||||
#define QMK_USAGE 0x61
|
||||
|
||||
void DetectQMKOpenRGBControllers(hid_device_info *info, const std::string&)
|
||||
{
|
||||
hid_device *dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
QMKOpenRGBController* controller = new QMKOpenRGBController(dev, info->path);
|
||||
unsigned int version = controller->GetProtocolVersion();
|
||||
|
||||
if(version == QMK_OPENRGB_PROTOCOL_VERSION)
|
||||
{
|
||||
RGBController_QMKOpenRGB* rgb_controller = new RGBController_QMKOpenRGB(controller);
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
delete controller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterQMKDetectors()
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Get QMKOpenRGB settings |
|
||||
\*-------------------------------------------------*/
|
||||
json qmk_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKOpenRGBDevices");
|
||||
|
||||
if(qmk_settings.contains("devices"))
|
||||
{
|
||||
for(unsigned int device_idx = 0; device_idx < qmk_settings["devices"].size(); device_idx++)
|
||||
{
|
||||
if( qmk_settings["devices"][device_idx].contains("usb_pid")
|
||||
&& qmk_settings["devices"][device_idx].contains("usb_vid")
|
||||
&& qmk_settings["devices"][device_idx].contains("name"))
|
||||
{
|
||||
std::string usb_pid_str = qmk_settings["devices"][device_idx]["usb_pid"];
|
||||
std::string usb_vid_str = qmk_settings["devices"][device_idx]["usb_vid"];
|
||||
std::string name = qmk_settings["devices"][device_idx]["name"];
|
||||
|
||||
/*-------------------------------------*\
|
||||
| Parse hex string to integer |
|
||||
\*-------------------------------------*/
|
||||
unsigned short usb_pid = std::stoi(usb_pid_str, 0, 16);
|
||||
unsigned short usb_vid = std::stoi(usb_vid_str, 0, 16);
|
||||
|
||||
REGISTER_DYNAMIC_HID_DETECTOR_IPU(name, DetectQMKOpenRGBControllers, usb_vid, usb_pid, 1, QMK_USAGE_PAGE, QMK_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_DYNAMIC_DETECTOR("QMK OpenRGB Devices", RegisterQMKDetectors);
|
||||
@@ -0,0 +1,727 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| RGBController_QMKOpenRGB.cpp |
|
||||
| |
|
||||
| Driver for QMK keyboards using OpenRGB Protocol |
|
||||
| |
|
||||
| Kasper 10th Octobber 2020 |
|
||||
| Jath03 28th May 2021 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#include "hsv.h"
|
||||
#include "RGBController_QMKOpenRGB.h"
|
||||
|
||||
RGBController_QMKOpenRGB::RGBController_QMKOpenRGB(QMKOpenRGBController* controller_ptr)
|
||||
{
|
||||
controller = controller_ptr;
|
||||
|
||||
name = controller->GetDeviceName();
|
||||
vendor = controller->GetDeviceVendor();
|
||||
description = "QMK OpenRGB Device (Protocol Version " + std::to_string(controller->GetProtocolVersion()) + ")";
|
||||
type = DEVICE_TYPE_KEYBOARD;
|
||||
location = controller->GetLocation();
|
||||
version = controller->GetQMKVersion();
|
||||
|
||||
unsigned int current_mode = 1;
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_OPENRGB_DIRECT))
|
||||
{
|
||||
InitializeMode("Direct", current_mode, MODE_FLAG_HAS_PER_LED_COLOR, MODE_COLORS_PER_LED);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_COLOR))
|
||||
{
|
||||
InitializeMode("Static", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_ALPHA_MOD))
|
||||
{
|
||||
InitializeMode("Alpha Mod", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_GRADIENT_UP_DOWN))
|
||||
{
|
||||
InitializeMode("Gradient Up Down", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_GRADIENT_LEFT_RIGHT))
|
||||
{
|
||||
InitializeMode("Gradient Left Right", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BREATHING))
|
||||
{
|
||||
InitializeMode("Breathing", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_SAT))
|
||||
{
|
||||
InitializeMode("Band Saturation", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_VAL))
|
||||
{
|
||||
InitializeMode("Band Value", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_PINWHEEL_SAT))
|
||||
{
|
||||
InitializeMode("Band Pinwheel Saturation", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_PINWHEEL_VAL))
|
||||
{
|
||||
InitializeMode("Band Pinwheel Value", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_SPIRAL_SAT))
|
||||
{
|
||||
InitializeMode("Band Spiral Saturation", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_BAND_SPIRAL_VAL))
|
||||
{
|
||||
InitializeMode("Band Spiral Value", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_ALL))
|
||||
{
|
||||
InitializeMode("Cycle All", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_LEFT_RIGHT))
|
||||
{
|
||||
InitializeMode("Cycle Left Right", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_UP_DOWN))
|
||||
{
|
||||
InitializeMode("Cycle Up Down", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_OUT_IN))
|
||||
{
|
||||
InitializeMode("Cycle Out In", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_OUT_IN_DUAL))
|
||||
{
|
||||
InitializeMode("Cycle Out In Dual", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_RAINBOW_MOVING_CHEVRON))
|
||||
{
|
||||
InitializeMode("Rainbow Moving Chevron", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_PINWHEEL))
|
||||
{
|
||||
InitializeMode("Cycle Pinwheel", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_CYCLE_SPIRAL))
|
||||
{
|
||||
InitializeMode("Cycle Spiral", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_DUAL_BEACON))
|
||||
{
|
||||
InitializeMode("Dual Beacon", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_RAINBOW_BEACON))
|
||||
{
|
||||
InitializeMode("Rainbow Beacon", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_RAINBOW_PINWHEELS))
|
||||
{
|
||||
InitializeMode("Rainbow Pinwheels", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_RAINDROPS))
|
||||
{
|
||||
InitializeMode("Raindrops", current_mode, 0, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_JELLYBEAN_RAINDROPS))
|
||||
{
|
||||
InitializeMode("Jellybean Raindrops", current_mode, 0, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_HUE_BREATHING))
|
||||
{
|
||||
InitializeMode("Hue Breathing", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_HUE_PENDULUM))
|
||||
{
|
||||
InitializeMode("Hue Pendulum", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_HUE_WAVE))
|
||||
{
|
||||
InitializeMode("Hue Wave", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_TYPING_HEATMAP))
|
||||
{
|
||||
InitializeMode("Typing Heatmap", current_mode, 0, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_DIGITAL_RAIN))
|
||||
{
|
||||
InitializeMode("Digital Rain", current_mode, 0, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_SIMPLE))
|
||||
{
|
||||
InitializeMode("Solid Reactive Simple", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE))
|
||||
{
|
||||
InitializeMode("Solid Reactive", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_WIDE))
|
||||
{
|
||||
InitializeMode("Solid Reactive Wide", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTIWIDE))
|
||||
{
|
||||
InitializeMode("Solid Reactive Multi Wide", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_CROSS))
|
||||
{
|
||||
InitializeMode("Solid Reactive Cross", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTICROSS))
|
||||
{
|
||||
InitializeMode("Solid Reactive Multi Cross", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_NEXUS))
|
||||
{
|
||||
InitializeMode("Solid Reactive Nexus", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_REACTIVE_MULTINEXUS))
|
||||
{
|
||||
InitializeMode("Solid Reactive Multi Nexus", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SPLASH))
|
||||
{
|
||||
InitializeMode("Rainbow Reactive Splash", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_MULTISPLASH))
|
||||
{
|
||||
InitializeMode("Rainbow Reactive Multi Splash", current_mode, MODE_FLAG_HAS_SPEED, MODE_COLORS_NONE);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_SPLASH))
|
||||
{
|
||||
InitializeMode("Solid Reactive Splash", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
if(controller->GetIsModeEnabled(QMK_OPENRGB_MODE_SOLID_MULTISPLASH))
|
||||
{
|
||||
InitializeMode("Solid Reactive Multi Splash", current_mode, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED, MODE_COLORS_MODE_SPECIFIC);
|
||||
}
|
||||
|
||||
active_mode = controller->GetMode() - 1;
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
RGBController_QMKOpenRGB::~RGBController_QMKOpenRGB()
|
||||
{
|
||||
for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++)
|
||||
{
|
||||
if(zones[zone_index].matrix_map != NULL)
|
||||
{
|
||||
delete zones[zone_index].matrix_map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::SetupZones()
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Get the number of LEDs from the device |
|
||||
\*---------------------------------------------------------*/
|
||||
const unsigned int total_number_of_leds = controller->GetTotalNumberOfLEDs();
|
||||
const unsigned int total_number_of_leds_with_empty_space = controller->GetTotalNumberOfLEDsWithEmptySpace();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Get information for each LED |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned int i = 0; i < std::max(total_number_of_leds, total_number_of_leds_with_empty_space); i++)
|
||||
{
|
||||
controller->GetLEDInfo(i);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Get LED vectors from controller |
|
||||
\*---------------------------------------------------------*/
|
||||
std::vector<point_t> led_points = controller->GetLEDPoints();
|
||||
std::vector<unsigned int> led_flags = controller->GetLEDFlags();
|
||||
std::vector<std::string> led_names = controller->GetLEDNames();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Count key LEDs and underglow LEDs |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned int number_of_key_leds;
|
||||
unsigned int number_of_underglow_leds;
|
||||
|
||||
CountKeyTypes(led_flags, total_number_of_leds, number_of_key_leds, number_of_underglow_leds);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Add LED names for underglow zone |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned int number_of_leds = number_of_key_leds + number_of_underglow_leds;
|
||||
bool has_underglow = number_of_underglow_leds > 0;
|
||||
|
||||
for(unsigned int i = 0; i < number_of_underglow_leds; i++)
|
||||
{
|
||||
led_names.push_back("Underglow: " + std::to_string(number_of_key_leds + i));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create sets for row and column position values |
|
||||
\*---------------------------------------------------------*/
|
||||
std::set<int> rows, columns;
|
||||
for (unsigned int i = 0; i < number_of_leds; i++)
|
||||
{
|
||||
rows.insert(led_points[i].y);
|
||||
columns.insert(led_points[i].x);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Calculate matrix map from QMK positions |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned int divisor = CalculateDivisor(led_points, rows, columns);
|
||||
|
||||
VectorMatrix matrix_map;
|
||||
VectorMatrix underglow_map;
|
||||
|
||||
PlaceLEDsInMaps(rows, columns, divisor, led_points, led_flags, matrix_map, underglow_map);
|
||||
CleanMatrixMaps(matrix_map, underglow_map, rows.size(), has_underglow);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| These vectors are class members because if they go out of |
|
||||
| scope, the underlying array (used by each zones' |
|
||||
| matrix_map) is unallocated. |
|
||||
\*---------------------------------------------------------*/
|
||||
flat_matrix_map = FlattenMatrixMap(matrix_map);
|
||||
flat_underglow_map = FlattenMatrixMap(underglow_map);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create Keyboard zone |
|
||||
\*---------------------------------------------------------*/
|
||||
zone keys_zone;
|
||||
keys_zone.name = "Keyboard";
|
||||
keys_zone.type = ZONE_TYPE_MATRIX;
|
||||
keys_zone.leds_min = number_of_key_leds;
|
||||
keys_zone.leds_max = keys_zone.leds_min;
|
||||
keys_zone.leds_count = keys_zone.leds_min;
|
||||
keys_zone.matrix_map = new matrix_map_type;
|
||||
keys_zone.matrix_map->width = matrix_map[0].size();
|
||||
keys_zone.matrix_map->height = matrix_map.size();
|
||||
keys_zone.matrix_map->map = flat_matrix_map.data();
|
||||
zones.push_back(keys_zone);
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create Underglow zone if it exists |
|
||||
\*---------------------------------------------------------*/
|
||||
if(has_underglow)
|
||||
{
|
||||
zone underglow_zone;
|
||||
underglow_zone.name = "Underglow";
|
||||
underglow_zone.type = ZONE_TYPE_MATRIX;
|
||||
underglow_zone.leds_min = number_of_underglow_leds;
|
||||
underglow_zone.leds_max = underglow_zone.leds_min;
|
||||
underglow_zone.leds_count = underglow_zone.leds_min;
|
||||
underglow_zone.matrix_map = new matrix_map_type;
|
||||
underglow_zone.matrix_map->width = underglow_map[0].size();
|
||||
underglow_zone.matrix_map->height = underglow_map.size();
|
||||
underglow_zone.matrix_map->map = flat_underglow_map.data();
|
||||
zones.push_back(underglow_zone);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Create LEDs |
|
||||
\*---------------------------------------------------------*/
|
||||
for(int led_idx = 0; led_idx < number_of_leds; led_idx++)
|
||||
{
|
||||
led keyboard_led;
|
||||
|
||||
if(led_idx < led_names.size())
|
||||
{
|
||||
keyboard_led.name = led_names[led_idx];
|
||||
}
|
||||
keyboard_led.value = led_idx;
|
||||
|
||||
leds.push_back(keyboard_led);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Setup Colors |
|
||||
\*---------------------------------------------------------*/
|
||||
SetupColors();
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| Initialize colors from device values |
|
||||
\*---------------------------------------------------------*/
|
||||
for(unsigned int i = 0; i < leds.size(); i++)
|
||||
{
|
||||
colors[i] = controller->GetLEDColors()[i];
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::DeviceUpdateLEDs()
|
||||
{
|
||||
controller->DirectModeSetLEDs(colors, controller->GetTotalNumberOfLEDs());
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::UpdateSingleLED(int led)
|
||||
{
|
||||
RGBColor color = colors[led];
|
||||
unsigned char red = RGBGetRValue(color);
|
||||
unsigned char grn = RGBGetGValue(color);
|
||||
unsigned char blu = RGBGetBValue(color);
|
||||
|
||||
controller->DirectModeSetSingleLED(led, red, grn, blu);
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::SetCustomMode()
|
||||
{
|
||||
active_mode = 0;
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::DeviceUpdateMode()
|
||||
{
|
||||
if(modes[active_mode].color_mode == MODE_COLORS_PER_LED)
|
||||
{
|
||||
controller->SetMode({ 0, 255, 255 }, modes[active_mode].value, 127);
|
||||
}
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_NONE)
|
||||
{
|
||||
controller->SetMode({ 0, 255, 255 }, modes[active_mode].value, modes[active_mode].speed);
|
||||
}
|
||||
else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC)
|
||||
{
|
||||
RGBColor rgb_color = modes[active_mode].colors[0];
|
||||
hsv_t hsv_color;
|
||||
rgb2hsv(rgb_color, &hsv_color);
|
||||
|
||||
if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED)
|
||||
{
|
||||
controller->SetMode(hsv_color, modes[active_mode].value, modes[active_mode].speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
controller->SetMode(hsv_color, modes[active_mode].value, 127);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::InitializeMode
|
||||
(
|
||||
std::string name,
|
||||
unsigned int ¤t_mode,
|
||||
unsigned int flags,
|
||||
unsigned int color_mode
|
||||
)
|
||||
{
|
||||
mode qmk_mode;
|
||||
qmk_mode.name = name;
|
||||
qmk_mode.value = current_mode++;
|
||||
qmk_mode.flags = flags;
|
||||
qmk_mode.color_mode = color_mode;
|
||||
|
||||
if(flags & MODE_FLAG_HAS_SPEED)
|
||||
{
|
||||
qmk_mode.speed_min = QMK_OPENRGB_SPEED_SLOWEST;
|
||||
qmk_mode.speed_max = QMK_OPENRGB_SPEED_FASTEST;
|
||||
qmk_mode.speed = QMK_OPENRGB_SPEED_NORMAL;
|
||||
}
|
||||
if(flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR)
|
||||
{
|
||||
qmk_mode.colors_min = 1;
|
||||
qmk_mode.colors_max = 1;
|
||||
qmk_mode.colors.resize(1);
|
||||
qmk_mode.colors[0] = controller->GetModeColor();
|
||||
}
|
||||
|
||||
modes.push_back(qmk_mode);
|
||||
}
|
||||
|
||||
unsigned int RGBController_QMKOpenRGB::CalculateDivisor
|
||||
(
|
||||
std::vector<point_t> led_points,
|
||||
std::set<int> rows,
|
||||
std::set<int> columns
|
||||
)
|
||||
{
|
||||
std::vector< std::vector<point_t> > row_points(rows.size());
|
||||
for(const point_t &pt : led_points)
|
||||
{
|
||||
for(const int &i : rows)
|
||||
{
|
||||
if(pt.y == i)
|
||||
{
|
||||
row_points[std::distance(rows.begin(), rows.find(i))].push_back(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int last_pos;
|
||||
std::vector<int> distances;
|
||||
for(const std::vector<point_t> &row : row_points)
|
||||
{
|
||||
last_pos = 0;
|
||||
std::for_each(row.begin(), row.end(), [&distances, &last_pos](const point_t &pt)
|
||||
{
|
||||
distances.push_back(pt.x - last_pos);
|
||||
last_pos = pt.x;
|
||||
});
|
||||
}
|
||||
std::map<int, int> counts;
|
||||
for(const int &i : distances)
|
||||
{
|
||||
counts[i]++;
|
||||
}
|
||||
|
||||
unsigned int divisor = distances[0];
|
||||
for(const std::pair<int, int> &i : counts)
|
||||
{
|
||||
if(counts[divisor] < i.second)
|
||||
{
|
||||
divisor = i.first;
|
||||
}
|
||||
}
|
||||
return divisor;
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::CountKeyTypes
|
||||
(
|
||||
std::vector<unsigned int> led_flags,
|
||||
unsigned int total_led_count,
|
||||
unsigned int& key_leds,
|
||||
unsigned int& underglow_leds
|
||||
)
|
||||
{
|
||||
underglow_leds = 0;
|
||||
key_leds = 0;
|
||||
|
||||
for(unsigned int i = 0; i < total_led_count; i++)
|
||||
{
|
||||
if(led_flags[i] & 2)
|
||||
{
|
||||
underglow_leds++;
|
||||
}
|
||||
else if(led_flags[i] != 0)
|
||||
{
|
||||
key_leds++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::PlaceLEDsInMaps
|
||||
(
|
||||
std::set<int> unique_rows,
|
||||
std::set<int> unique_cols,
|
||||
unsigned int divisor,
|
||||
std::vector<point_t> led_points,
|
||||
std::vector<unsigned int> led_flags,
|
||||
VectorMatrix& matrix_map_xl,
|
||||
VectorMatrix& underglow_map_xl
|
||||
)
|
||||
{
|
||||
matrix_map_xl = MakeEmptyMatrixMap(unique_rows.size(), std::round(255/divisor) + 10);
|
||||
underglow_map_xl = MakeEmptyMatrixMap(unique_rows.size(), std::round(255/divisor) + 10);
|
||||
|
||||
unsigned int x = 0;
|
||||
unsigned int y = 0;
|
||||
unsigned int openrgb_idx = 0;
|
||||
unsigned int underglow_counter = 0;
|
||||
|
||||
for(unsigned int i = 0; i < controller->GetTotalNumberOfLEDs(); i++)
|
||||
{
|
||||
if(led_points[i].x != 255 && led_points[i].y != 255)
|
||||
{
|
||||
bool underglow = led_flags[i] & 2;
|
||||
|
||||
x = std::round(led_points[i].x/divisor);
|
||||
y = std::distance(unique_rows.begin(), unique_rows.find(led_points[i].y));
|
||||
|
||||
if(!underglow)
|
||||
{
|
||||
while(matrix_map_xl[y][x] != NO_LED)
|
||||
{
|
||||
x++;
|
||||
}
|
||||
matrix_map_xl[y][x] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(underglow_map_xl[y][x] != NO_LED)
|
||||
{
|
||||
x++;
|
||||
}
|
||||
underglow_map_xl[y][x] = underglow_counter;
|
||||
underglow_counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VectorMatrix RGBController_QMKOpenRGB::MakeEmptyMatrixMap
|
||||
(
|
||||
unsigned int height,
|
||||
unsigned int width
|
||||
)
|
||||
{
|
||||
std::vector<std::vector<unsigned int> > matrix_map(height);
|
||||
for (int i = 0; i < height; i++)
|
||||
{
|
||||
for (int j = 0; j < width; j++)
|
||||
{
|
||||
matrix_map[i].push_back(NO_LED);
|
||||
}
|
||||
}
|
||||
return matrix_map;
|
||||
}
|
||||
|
||||
void RGBController_QMKOpenRGB::CleanMatrixMaps
|
||||
(
|
||||
VectorMatrix& matrix_map,
|
||||
VectorMatrix& underglow_map,
|
||||
unsigned int height,
|
||||
bool has_underglow
|
||||
)
|
||||
{
|
||||
bool empty_col = true;
|
||||
bool empty_col_udg = true;
|
||||
bool empty_row = true;
|
||||
int width = 0;
|
||||
int width_udg = 0;
|
||||
|
||||
std::vector<int> empty_rows;
|
||||
|
||||
bool can_break;
|
||||
bool can_break_udg;
|
||||
|
||||
for(unsigned int i = 0; i < height; i++)
|
||||
{
|
||||
empty_row = true;
|
||||
can_break = false;
|
||||
can_break_udg = false;
|
||||
|
||||
for(std::size_t j = matrix_map[i].size() - 1; j --> 0; )
|
||||
{
|
||||
if(matrix_map[i][j] != NO_LED && width < (j + 1) && !can_break)
|
||||
{
|
||||
width = (j + 1);
|
||||
can_break = true;
|
||||
empty_row = false;
|
||||
}
|
||||
else if(matrix_map[i][j] != NO_LED)
|
||||
{
|
||||
empty_row = false;
|
||||
}
|
||||
if(underglow_map[i][j] != NO_LED && width_udg < (j + 1) && !can_break_udg)
|
||||
{
|
||||
width_udg = (j + 1);
|
||||
can_break_udg = true;
|
||||
}
|
||||
if (can_break && can_break_udg) break;
|
||||
}
|
||||
|
||||
if(matrix_map[i][0] != NO_LED)
|
||||
{
|
||||
empty_col = false;
|
||||
}
|
||||
|
||||
if(underglow_map[i][0] != NO_LED)
|
||||
{
|
||||
empty_col_udg = false;
|
||||
}
|
||||
|
||||
if(empty_row)
|
||||
{
|
||||
empty_rows.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int new_height = height - empty_rows.size();
|
||||
width = empty_col ? width - 1 : width;
|
||||
width_udg = empty_col_udg && empty_col ? width_udg - 1 : width_udg;
|
||||
|
||||
for(unsigned int i = empty_rows.size(); i --> 0; )
|
||||
{
|
||||
matrix_map.erase(matrix_map.begin()+empty_rows[i]);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < new_height; i++)
|
||||
{
|
||||
if(empty_col)
|
||||
{
|
||||
matrix_map[i].erase(matrix_map[i].begin(), matrix_map[i].begin() + 1);
|
||||
}
|
||||
|
||||
if(empty_col_udg && empty_col)
|
||||
{
|
||||
underglow_map[i].erase(underglow_map[i].begin(), underglow_map[i].begin() + 1);
|
||||
}
|
||||
|
||||
matrix_map[i].erase(matrix_map[i].begin()+width, matrix_map[i].end());
|
||||
|
||||
if(has_underglow)
|
||||
{
|
||||
underglow_map[i].erase(underglow_map[i].begin()+width_udg, underglow_map[i].end());
|
||||
}
|
||||
}
|
||||
|
||||
if(has_underglow)
|
||||
{
|
||||
for(unsigned int i = new_height; i < height; i++)
|
||||
{
|
||||
underglow_map[i].erase(underglow_map[i].begin()+width_udg, underglow_map[i].end());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<unsigned int> RGBController_QMKOpenRGB::FlattenMatrixMap
|
||||
(
|
||||
VectorMatrix matrix_map
|
||||
)
|
||||
{
|
||||
std::vector<unsigned int> flat_map;
|
||||
|
||||
for(const std::vector<unsigned int> &row : matrix_map)
|
||||
{
|
||||
for(const unsigned int &item : row)
|
||||
{
|
||||
flat_map.push_back(item);
|
||||
}
|
||||
}
|
||||
return flat_map;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*-------------------------------------------------------------------*\
|
||||
| RGBController_QMKOpenRGB.h |
|
||||
| |
|
||||
| Driver for QMK keyboards using OpenRGB Protocol |
|
||||
| |
|
||||
| Kasper 10th Octobber 2020 |
|
||||
| Jath03 28th May 2021 |
|
||||
\*-------------------------------------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "QMKOpenRGBController.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#define NO_LED 0xFFFFFFFF
|
||||
|
||||
typedef std::vector<std::vector<unsigned int>> VectorMatrix;
|
||||
|
||||
class RGBController_QMKOpenRGB : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_QMKOpenRGB(QMKOpenRGBController* controller_ptr);
|
||||
~RGBController_QMKOpenRGB();
|
||||
|
||||
void SetupZones();
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void SetCustomMode();
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
QMKOpenRGBController* controller;
|
||||
std::vector<unsigned int> flat_matrix_map;
|
||||
std::vector<unsigned int> flat_underglow_map;
|
||||
|
||||
void InitializeMode
|
||||
(
|
||||
std::string name,
|
||||
unsigned int ¤t_mode,
|
||||
unsigned int flags,
|
||||
unsigned int color_mode
|
||||
);
|
||||
|
||||
unsigned int CalculateDivisor
|
||||
(
|
||||
std::vector<point_t> led_points,
|
||||
std::set<int> rows,
|
||||
std::set<int> columns
|
||||
);
|
||||
|
||||
void CountKeyTypes
|
||||
(
|
||||
std::vector<unsigned int> led_flags,
|
||||
unsigned int total_led_count,
|
||||
unsigned int& key_leds,
|
||||
unsigned int& underglow_leds
|
||||
);
|
||||
|
||||
void PlaceLEDsInMaps
|
||||
(
|
||||
std::set<int> unique_rows,
|
||||
std::set<int> unique_cols,
|
||||
unsigned int divisor,
|
||||
std::vector<point_t> led_points,
|
||||
std::vector<unsigned int> led_flags,
|
||||
VectorMatrix& matrix_map_xl,
|
||||
VectorMatrix& underglow_map_xl
|
||||
);
|
||||
|
||||
VectorMatrix MakeEmptyMatrixMap
|
||||
(
|
||||
unsigned int height,
|
||||
unsigned int width
|
||||
);
|
||||
|
||||
void CleanMatrixMaps
|
||||
(
|
||||
VectorMatrix& matrix_map,
|
||||
VectorMatrix& underglow_map,
|
||||
unsigned int height,
|
||||
bool has_underglow
|
||||
);
|
||||
|
||||
std::vector<unsigned int> FlattenMatrixMap
|
||||
(
|
||||
VectorMatrix matrix_map
|
||||
);
|
||||
};
|
||||
+19
-9
@@ -2,12 +2,22 @@
|
||||
|
||||
#include "DeviceDetector.h"
|
||||
|
||||
#define REGISTER_DETECTOR(name, func) static DeviceDetector device_detector_obj_##func(name, func)
|
||||
#define REGISTER_I2C_DETECTOR(name, func) static I2CDeviceDetector device_detector_obj_##func(name, func)
|
||||
#define REGISTER_I2C_BUS_DETECTOR(func) static I2CBusDetector device_detector_obj_##func(func)
|
||||
#define REGISTER_HID_DETECTOR(name, func, vid, pid) static HIDDeviceDetector device_detector_obj_##vid##pid(name, func, vid, pid, HID_INTERFACE_ANY, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_I(name, func, vid, pid, interface) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface(name, func, vid, pid, interface, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_IP(name, func, vid, pid, interface, page) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page(name, func, vid, pid, interface, page, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_IPU(name, func, vid, pid, interface, page, usage) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page##_##usage(name, func, vid, pid, interface, page, usage)
|
||||
#define REGISTER_HID_DETECTOR_P(name, func, vid, pid, page) static HIDDeviceDetector device_detector_obj_##vid##pid##__##page(name, func, vid, pid, HID_INTERFACE_ANY, page, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_PU(name, func, vid, pid, page, usage) static HIDDeviceDetector device_detector_obj_##vid##pid##__##page##_##usage(name, func, vid, pid, HID_INTERFACE_ANY, page, usage)
|
||||
#define REGISTER_DETECTOR(name, func) static DeviceDetector device_detector_obj_##func(name, func)
|
||||
#define REGISTER_I2C_DETECTOR(name, func) static I2CDeviceDetector device_detector_obj_##func(name, func)
|
||||
#define REGISTER_I2C_BUS_DETECTOR(func) static I2CBusDetector device_detector_obj_##func(func)
|
||||
#define REGISTER_HID_DETECTOR(name, func, vid, pid) static HIDDeviceDetector device_detector_obj_##vid##pid(name, func, vid, pid, HID_INTERFACE_ANY, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_I(name, func, vid, pid, interface) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface(name, func, vid, pid, interface, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_IP(name, func, vid, pid, interface, page) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page(name, func, vid, pid, interface, page, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_IPU(name, func, vid, pid, interface, page, usage) static HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page##_##usage(name, func, vid, pid, interface, page, usage)
|
||||
#define REGISTER_HID_DETECTOR_P(name, func, vid, pid, page) static HIDDeviceDetector device_detector_obj_##vid##pid##__##page(name, func, vid, pid, HID_INTERFACE_ANY, page, HID_USAGE_ANY)
|
||||
#define REGISTER_HID_DETECTOR_PU(name, func, vid, pid, page, usage) static HIDDeviceDetector device_detector_obj_##vid##pid##__##page##_##usage(name, func, vid, pid, HID_INTERFACE_ANY, page, usage)
|
||||
#define REGISTER_DYNAMIC_DETECTOR(name, func) static DynamicDetector device_detector_obj_##func(name, func)
|
||||
|
||||
#define REGISTER_DYNAMIC_I2C_DETECTOR(name, func) I2CDeviceDetector device_detector_obj_##func(name, func)
|
||||
#define REGISTER_DYNAMIC_I2C_BUS_DETECTOR(func) I2CBusDetector device_detector_obj_##func(func)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR(name, func, vid, pid) HIDDeviceDetector device_detector_obj_##vid##pid(name, func, vid, pid, HID_INTERFACE_ANY, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR_I(name, func, vid, pid, interface) HIDDeviceDetector device_detector_obj_##vid##pid##_##interface(name, func, vid, pid, interface, HID_USAGE_PAGE_ANY, HID_USAGE_ANY)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR_IP(name, func, vid, pid, interface, page) HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page(name, func, vid, pid, interface, page, HID_USAGE_ANY)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR_IPU(name, func, vid, pid, interface, page, usage) HIDDeviceDetector device_detector_obj_##vid##pid##_##interface##_##page##_##usage(name, func, vid, pid, interface, page, usage)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR_P(name, func, vid, pid, page) HIDDeviceDetector device_detector_obj_##vid##pid##__##page(name, func, vid, pid, HID_INTERFACE_ANY, page, HID_USAGE_ANY)
|
||||
#define REGISTER_DYNAMIC_HID_DETECTOR_PU(name, func, vid, pid, page, usage) HIDDeviceDetector device_detector_obj_##vid##pid##__##page##_##usage(name, func, vid, pid, HID_INTERFACE_ANY, page, usage)
|
||||
@@ -41,3 +41,12 @@ public:
|
||||
ResourceManager::get()->RegisterHIDDeviceDetector(name, detector, vid, pid, interface, usage_page, usage);
|
||||
}
|
||||
};
|
||||
|
||||
class DynamicDetector
|
||||
{
|
||||
public:
|
||||
DynamicDetector(std::string name, DynamicDetectorFunction detector)
|
||||
{
|
||||
ResourceManager::get()->RegisterDynamicDetector(name, detector);
|
||||
}
|
||||
};
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
| |
|
||||
| 0: Initial (unversioned) protocol |
|
||||
| 1: Add versioning, vendor string (Release 0.5) |
|
||||
| 2: Add profile controls |
|
||||
| 2: Add profile controls (Release 0.6) |
|
||||
\*-----------------------------------------------------*/
|
||||
#define OPENRGB_SDK_PROTOCOL_VERSION 2
|
||||
|
||||
|
||||
+13
-1
@@ -23,7 +23,7 @@ greaterThan(QT_MAJOR_VERSION, 5): DEFINES += _QT6
|
||||
#-----------------------------------------------------------------------------------------------#
|
||||
# Application Configuration #
|
||||
#-----------------------------------------------------------------------------------------------#
|
||||
VERSION = 0.51
|
||||
VERSION = 0.6
|
||||
TARGET = OpenRGB
|
||||
TEMPLATE = app
|
||||
|
||||
@@ -111,6 +111,7 @@ INCLUDEPATH +=
|
||||
Controllers/OpenRazerController/ \
|
||||
Controllers/PatriotViperController/ \
|
||||
Controllers/PhilipsWizController/ \
|
||||
Controllers/QMKOpenRGBController/ \
|
||||
Controllers/RazerController/ \
|
||||
Controllers/RedragonController/ \
|
||||
Controllers/RoccatController/ \
|
||||
@@ -128,6 +129,7 @@ INCLUDEPATH +=
|
||||
qt/
|
||||
|
||||
HEADERS += \
|
||||
Controllers/LogitechController/LogitechProtocolCommon.h \
|
||||
dependencies/ColorWheel/ColorWheel.h \
|
||||
dependencies/json/json.hpp \
|
||||
dependencies/libcmmk/include/libcmmk/libcmmk.h \
|
||||
@@ -283,6 +285,7 @@ HEADERS +=
|
||||
Controllers/LogitechController/LogitechG910Controller.h \
|
||||
Controllers/LogitechController/LogitechG815Controller.h \
|
||||
Controllers/LogitechController/LogitechGLightsyncController.h \
|
||||
Controllers/LogitechController/LogitechLightspeedController.h \
|
||||
Controllers/LogitechController/RGBController_LogitechG203L.h \
|
||||
Controllers/LogitechController/RGBController_LogitechG213.h \
|
||||
Controllers/LogitechController/RGBController_LogitechG560.h \
|
||||
@@ -292,6 +295,7 @@ HEADERS +=
|
||||
Controllers/LogitechController/RGBController_LogitechGLightsync.h \
|
||||
Controllers/LogitechController/RGBController_LogitechGLightsync1zone.h \
|
||||
Controllers/LogitechController/RGBController_LogitechGPowerPlay.h \
|
||||
Controllers/LogitechController/RGBController_LogitechLightspeed.h \
|
||||
Controllers/MSI3ZoneController/MSI3ZoneController.h \
|
||||
Controllers/MSI3ZoneController/RGBController_MSI3Zone.h \
|
||||
Controllers/MSIGPUController/MSIGPUController.h \
|
||||
@@ -314,6 +318,8 @@ HEADERS +=
|
||||
Controllers/PatriotViperController/RGBController_PatriotViper.h \
|
||||
Controllers/PhilipsWizController/PhilipsWizController.h \
|
||||
Controllers/PhilipsWizController/RGBController_PhilipsWiz.h \
|
||||
Controllers/QMKOpenRGBController/QMKOpenRGBController.h \
|
||||
Controllers/QMKOpenRGBController/RGBController_QMKOpenRGB.h \
|
||||
Controllers/RazerController/RazerController.h \
|
||||
Controllers/RazerController/RazerKrakenController.h \
|
||||
Controllers/RazerController/RazerDevices.h \
|
||||
@@ -367,6 +373,7 @@ HEADERS +=
|
||||
RGBController/RGBController_Network.h \
|
||||
|
||||
SOURCES += \
|
||||
Controllers/LogitechController/LogitechProtocolCommon.cpp \
|
||||
dependencies/dmiinfo.cpp \
|
||||
dependencies/ColorWheel/ColorWheel.cpp \
|
||||
dependencies/libe131/src/e131.c \
|
||||
@@ -562,6 +569,7 @@ SOURCES +=
|
||||
Controllers/LogitechController/LogitechG910Controller.cpp \
|
||||
Controllers/LogitechController/LogitechG815Controller.cpp \
|
||||
Controllers/LogitechController/LogitechGLightsyncController.cpp \
|
||||
Controllers/LogitechController/LogitechLightspeedController.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechG203L.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechG213.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechG560.cpp \
|
||||
@@ -571,6 +579,7 @@ SOURCES +=
|
||||
Controllers/LogitechController/RGBController_LogitechGLightsync.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechGLightsync1zone.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp \
|
||||
Controllers/LogitechController/RGBController_LogitechLightspeed.cpp \
|
||||
Controllers/MSI3ZoneController/MSI3ZoneController.cpp \
|
||||
Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp \
|
||||
Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp \
|
||||
@@ -600,6 +609,9 @@ SOURCES +=
|
||||
Controllers/PhilipsWizController/PhilipsWizController.cpp \
|
||||
Controllers/PhilipsWizController/PhilipsWizControllerDetect.cpp \
|
||||
Controllers/PhilipsWizController/RGBController_PhilipsWiz.cpp \
|
||||
Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp \
|
||||
Controllers/QMKOpenRGBController/QMKOpenRGBController.cpp \
|
||||
Controllers/QMKOpenRGBController/RGBController_QMKOpenRGB.cpp \
|
||||
Controllers/RazerController/RazerController.cpp \
|
||||
Controllers/RazerController/RazerKrakenController.cpp \
|
||||
Controllers/RazerController/RazerControllerDetect.cpp \
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
##  (formerly OpenAuraSDK)
|
||||
## 
|
||||
|
||||
 
|
||||
|
||||
Visit our website at https://openrgb.org!
|
||||
|
||||
One of the biggest complaints about RGB is the software ecosystem surrounding it. Every manufacturer has their own app, their own brand, their own style. If you want to mix and match devices, you end up with a ton of conflicting, functionally identical apps competing for your background resources. On top of that, these apps are proprietary and Windows-only. Some even require online accounts. What if there was a way to control all of your RGB devices from a single app, on both Windows and Linux, without any nonsense? That is what OpenRGB sets out to achieve. One app to rule them all.
|
||||
|
||||
## Features
|
||||
|
||||
+30
-5
@@ -37,11 +37,12 @@ ResourceManager::ResourceManager()
|
||||
/*-------------------------------------------------------------------------*\
|
||||
| Initialize Detection Variables |
|
||||
\*-------------------------------------------------------------------------*/
|
||||
detection_enabled = true;
|
||||
detection_percent = 100;
|
||||
detection_string = "";
|
||||
detection_is_required = false;
|
||||
DetectDevicesThread = nullptr;
|
||||
detection_enabled = true;
|
||||
detection_percent = 100;
|
||||
detection_string = "";
|
||||
detection_is_required = false;
|
||||
DetectDevicesThread = nullptr;
|
||||
dynamic_detectors_processed = false;
|
||||
|
||||
SetupConfigurationDirectory();
|
||||
|
||||
@@ -185,6 +186,12 @@ void ResourceManager::RegisterHIDDeviceDetector(std::string name,
|
||||
hid_device_detector_strings.push_back(name);
|
||||
}
|
||||
|
||||
void ResourceManager::RegisterDynamicDetector(std::string name, DynamicDetectorFunction detector)
|
||||
{
|
||||
dynamic_detector_strings.push_back(name);
|
||||
dynamic_detectors.push_back(detector);
|
||||
}
|
||||
|
||||
void ResourceManager::RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg)
|
||||
{
|
||||
DeviceListChangeCallbacks.push_back(new_callback);
|
||||
@@ -503,8 +510,26 @@ void ResourceManager::Cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
void ResourceManager::ProcessDynamicDetectors()
|
||||
{
|
||||
for(unsigned int detector_idx = 0; detector_idx < dynamic_detectors.size(); detector_idx++)
|
||||
{
|
||||
dynamic_detectors[detector_idx]();
|
||||
}
|
||||
|
||||
dynamic_detectors_processed = true;
|
||||
}
|
||||
|
||||
void ResourceManager::DetectDevices()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Process Dynamic Detectors |
|
||||
\*-----------------------------------------------------*/
|
||||
if(!dynamic_detectors_processed)
|
||||
{
|
||||
ProcessDynamicDetectors();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Call detection start callbacks |
|
||||
\*-----------------------------------------------------*/
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef std::function<void()> I2CBusDetect
|
||||
typedef std::function<void(std::vector<RGBController*>&)> DeviceDetectorFunction;
|
||||
typedef std::function<void(std::vector<i2c_smbus_interface*>&)> I2CDeviceDetectorFunction;
|
||||
typedef std::function<void(hid_device_info*, const std::string&)> HIDDeviceDetectorFunction;
|
||||
typedef std::function<void()> DynamicDetectorFunction;
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
@@ -111,6 +112,7 @@ public:
|
||||
int interface = HID_INTERFACE_ANY,
|
||||
int usage_page = HID_USAGE_PAGE_ANY,
|
||||
int usage = HID_USAGE_ANY);
|
||||
void RegisterDynamicDetector (std::string name, DynamicDetectorFunction detector);
|
||||
|
||||
void RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg);
|
||||
void RegisterDetectionProgressCallback(DetectionProgressCallback new_callback, void * new_callback_arg);
|
||||
@@ -135,6 +137,7 @@ public:
|
||||
|
||||
void SetConfigurationDirectory(std::string directory);
|
||||
|
||||
void ProcessDynamicDetectors();
|
||||
void UpdateDeviceList();
|
||||
void DeviceListChanged();
|
||||
void DetectionProgressChanged();
|
||||
@@ -207,6 +210,10 @@ private:
|
||||
std::vector<std::string> i2c_device_detector_strings;
|
||||
std::vector<HIDDeviceDetectorBlock> hid_device_detectors;
|
||||
std::vector<std::string> hid_device_detector_strings;
|
||||
std::vector<DynamicDetectorFunction> dynamic_detectors;
|
||||
std::vector<std::string> dynamic_detector_strings;
|
||||
|
||||
bool dynamic_detectors_processed;
|
||||
|
||||
/*-------------------------------------------------------------------------------------*\
|
||||
| Detection Thread and Detection State |
|
||||
|
||||
@@ -1167,7 +1167,7 @@ unsigned int cli_pre_detection(int argc, char *argv[])
|
||||
print_help = true;
|
||||
break;
|
||||
}
|
||||
cfg_args++;
|
||||
cfg_args+= 2;
|
||||
arg_index++;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
openrgb (0.51.1) UNRELEASED; urgency=medium
|
||||
openrgb (0.6.0) UNRELEASED; urgency=medium
|
||||
|
||||
* Builds from git master. See git history for more information.
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -5,7 +5,8 @@ set -u -o pipefail
|
||||
|
||||
# Reload rules
|
||||
if [ -f /bin/udevadm ]; then
|
||||
udevadm control --reload-rules && udevadm trigger;
|
||||
udevadm control --reload-rules || echo "done"
|
||||
udevadm trigger;
|
||||
else
|
||||
echo
|
||||
echo "\/-------------------------------------------------------\\"
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
%global _name OpenRGB
|
||||
|
||||
Name: openrgb
|
||||
Version: 0.5
|
||||
Version: 0.6
|
||||
Release: 1%{?dist}
|
||||
Summary: Open source RGB lighting control that doesn't depend on manufacturer software
|
||||
|
||||
@@ -50,6 +50,9 @@ fi
|
||||
%doc README.md
|
||||
|
||||
%changelog
|
||||
* Mon May 31 2021 Adam Honse <[email protected]> - 0.6-0
|
||||
- Updated to 0.6
|
||||
|
||||
* Mon May 03 2021 Pol Rius <[email protected]> - 0.5-0
|
||||
- Modified to build in Gitlab's CI
|
||||
|
||||
|
||||
+14
-2
@@ -4,9 +4,21 @@
|
||||
#if defined(__has_include) && __has_include(<filesystem>)
|
||||
|
||||
#include <filesystem>
|
||||
namespace filesystem = std::filesystem;
|
||||
|
||||
#else
|
||||
// Debian 10 provides the header, but does not enable the feature, so we additionally check for the feature test macro
|
||||
// MSVC below 2017 does not provide feature test macros, so we leave an exception for them
|
||||
#if defined(__cpp_lib_filesystem) || defined (_MSC_VER)
|
||||
namespace filesystem = std::filesystem;
|
||||
#define STD_FILESYSTEM_FOUND
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef STD_FILESYSTEM_FOUND
|
||||
|
||||
#if defined(__has_include) && !__has_include(<experimental/filesystem>)
|
||||
#error Neither <filesystem> nor <experimental/filesystem> could be found on the system! Please report an issue to OpenRGB developers providing your system info.
|
||||
#endif
|
||||
|
||||
#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING
|
||||
#include <experimental/filesystem>
|
||||
|
||||
@@ -129,6 +129,19 @@ bool AttemptLocalConnection()
|
||||
ResourceManager::get()->RegisterNetworkClient(client);
|
||||
|
||||
success = true;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Wait up to 5 seconds for the client connection to |
|
||||
| retrieve all controllers |
|
||||
\*-----------------------------------------------------*/
|
||||
for(int timeout = 0; timeout < 1000; timeout++)
|
||||
{
|
||||
if(client->GetOnline())
|
||||
{
|
||||
break;
|
||||
}
|
||||
std::this_thread::sleep_for(5ms);
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
+1
-1
@@ -224,7 +224,7 @@ void DeviceView::setController(RGBController * controller_ptr)
|
||||
unsigned int map_idx = led_y * map->width + led_x;
|
||||
unsigned int color_idx = map->map[map_idx] + controller->zones[zone_idx].start_idx;
|
||||
|
||||
if(color_idx != 0xFFFFFFFF && color_idx < led_pos.size())
|
||||
if(map->map[map_idx] != 0xFFFFFFFF && color_idx < led_pos.size())
|
||||
{
|
||||
led_pos[color_idx].matrix_x = (zone_pos[zone_idx].matrix_x + led_x + ledPadding) * atom;
|
||||
led_pos[color_idx].matrix_y = current_y + (led_y + ledPadding) * atom;
|
||||
|
||||
@@ -23,6 +23,12 @@ OpenRGBSettingsPage::OpenRGBSettingsPage(QWidget *parent) :
|
||||
std::string theme = theme_settings["theme"];
|
||||
ui->ComboBoxTheme->setCurrentText(QString::fromStdString(theme));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->ComboBoxTheme->setCurrentText(QString::fromStdString(("light")));
|
||||
}
|
||||
|
||||
theme_initialized = true;
|
||||
#else
|
||||
ui->ComboBoxTheme->hide();
|
||||
ui->ThemeLabel->hide();
|
||||
@@ -59,10 +65,13 @@ OpenRGBSettingsPage::~OpenRGBSettingsPage()
|
||||
|
||||
void OpenRGBSettingsPage::on_ComboBoxTheme_currentTextChanged(const QString theme)
|
||||
{
|
||||
json theme_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Theme");
|
||||
theme_settings["theme"] = theme.toStdString();
|
||||
ResourceManager::get()->GetSettingsManager()->SetSettings("Theme", theme_settings);
|
||||
SaveSettings();
|
||||
if(theme_initialized)
|
||||
{
|
||||
json theme_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Theme");
|
||||
theme_settings["theme"] = theme.toStdString();
|
||||
ResourceManager::get()->GetSettingsManager()->SetSettings("Theme", theme_settings);
|
||||
SaveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenRGBSettingsPage::on_CheckboxMinimizeOnClose_clicked()
|
||||
|
||||
@@ -20,6 +20,8 @@ private:
|
||||
Ui::OpenRGBSettingsPageUi *ui;
|
||||
void SaveSettings();
|
||||
|
||||
bool theme_initialized = false;
|
||||
|
||||
private slots:
|
||||
void on_ComboBoxTheme_currentTextChanged(const QString);
|
||||
void on_CheckboxMinimizeOnClose_clicked();
|
||||
|
||||
@@ -12,11 +12,7 @@ set -e
|
||||
# Use RAM disk if possible (if available and not building on a CI #
|
||||
# system like Travis) #
|
||||
#-----------------------------------------------------------------------#
|
||||
if [ "$CI" == "" ] && [ -d /dev/shm ]; then
|
||||
TEMP_BASE=/dev/shm
|
||||
else
|
||||
TEMP_BASE=/tmp
|
||||
fi
|
||||
TEMP_BASE=/tmp
|
||||
BUILD_DIR=$(mktemp -d -p "$TEMP_BASE" appimage-build-XXXXXX)
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
@@ -72,20 +68,15 @@ qmake "$REPO_ROOT"
|
||||
make -j$(nproc) TARGET="$TARGET"
|
||||
make install INSTALL_ROOT=AppDir
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Make them executable #
|
||||
#-----------------------------------------------------------------------#
|
||||
chmod +x "$REPO_ROOT"/scripts/tools/linuxdeploy*.AppImage
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Make sure Qt plugin finds QML sources so it can deploy the imported #
|
||||
# files #
|
||||
#-----------------------------------------------------------------------#
|
||||
export QML_SOURCES_PATHS="$REPO_ROOT"/src
|
||||
|
||||
"$REPO_ROOT"/scripts/tools/linuxdeploy-"$ARCH".AppImage --appimage-extract-and-run --appdir AppDir -e "$TARGET" -i "$REPO_ROOT"/qt/OpenRGB.png -d "$REPO_ROOT"/qt/OpenRGB.desktop
|
||||
"$REPO_ROOT"/scripts/tools/linuxdeploy-plugin-qt-"$ARCH".AppImage --appimage-extract-and-run --appdir AppDir
|
||||
"$REPO_ROOT"/scripts/tools/linuxdeploy-"$ARCH".AppImage --appimage-extract-and-run --appdir AppDir --output appimage
|
||||
linuxdeploy-"$ARCH".AppImage --appdir AppDir -e "$TARGET" -i "$REPO_ROOT"/qt/OpenRGB.png -d "$REPO_ROOT"/qt/OpenRGB.desktop
|
||||
linuxdeploy-plugin-qt-"$ARCH".AppImage --appdir AppDir
|
||||
linuxdeploy-"$ARCH".AppImage --appdir AppDir --output appimage
|
||||
|
||||
#-----------------------------------------------------------------------#
|
||||
# Move built AppImage back into original CWD #
|
||||
|
||||
Reference in New Issue
Block a user