Compare commits
34
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
befb783f2d | ||
|
|
fe11115f32 | ||
|
|
9a00f1d6d8 | ||
|
|
b7e2103f41 | ||
|
|
87043cde65 | ||
|
|
2aaf7017ee | ||
|
|
22acdd1fed | ||
|
|
4e4eade335 | ||
|
|
9f7812bc7b | ||
|
|
6029a5b0c5 | ||
|
|
74a49ec3e6 | ||
|
|
21dd2ee66a | ||
|
|
f76d78775c | ||
|
|
af01ff5de3 | ||
|
|
f2f84fc7e3 | ||
|
|
939f46c025 | ||
|
|
a1469041e5 | ||
|
|
f39b57fadc | ||
|
|
08a985a216 | ||
|
|
7054badf4f | ||
|
|
332a04f94c | ||
|
|
ae88771e79 | ||
|
|
09e524314f | ||
|
|
8e8573e7d0 | ||
|
|
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:buster-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:buster-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:buster-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:buster-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 libmbedtls-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 libmbedtls-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 #
|
||||
#-----------------------------------------------------------------------#
|
||||
|
||||
@@ -52,7 +52,12 @@ char* AMDWraithPrismController::GetDeviceName()
|
||||
std::string AMDWraithPrismController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -54,8 +54,13 @@ std::string PolychromeUSBController::GetDeviceName()
|
||||
std::string PolychromeUSBController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
|
||||
@@ -40,7 +40,12 @@ std::string AuraCoreController::GetDeviceLocation()
|
||||
std::string AuraCoreController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -33,13 +33,19 @@ typedef struct
|
||||
static const gpu_pci_device device_list[] =
|
||||
{
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_GTX1060_STRIX, 0x29, "ASUS GTX 1060 Strix" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_GTX1070_STRIX, 0x29, "ASUS GTX 1070 Strix OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_GTX1070_STRIX_GAMING, 0x29, "ASUS GTX 1070 Strix Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_GTX1070_STRIX_OC, 0x29, "ASUS GTX 1070 Strix OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_GTX1080_STRIX, 0x29, "ASUS GTX 1080 Strix OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_A8G_GAMING, 0x29, "ASUS ROG Strix GTX1080 A8G Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_O8G_GAMING, 0x29, "ASUS ROG Strix GTX1080 O8G Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_GAMING, 0x29, "ASUS ROG Strix GTX1080 Ti Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, ASUS_SUB_VEN, ASUS_ROG_GTX1660TI_OC, 0x2A, "ASUS ROG GTX 1660 Ti OC 6G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_EVO_GAMING, 0x2A, "ASUS ROG STRIX RTX 2060 EVO Gaming 6G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_EVO_GAMING, 0x2A, "ASUS ROG STRIX RTX 2060S A8G EVO Gaming 6G"},
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_A8G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2070 A8G Gaming 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_O8G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2070 O8G Gaming 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2070S A8G Gaming 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_O8G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2070S O8G Gaming 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_O8G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2080 O8G Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_O11G_GAMING, 0x2A, "ASUS ROG STRIX RTX 2080 Ti O11G Gaming" },
|
||||
{ AMD_GPU_VEN, AMD_VEGA10_DEV, ASUS_SUB_VEN, ASUS_VEGA64_STRIX, 0x29, "ASUS Vega 64 Strix" },
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string AuraKeyboardController::GetDeviceLocation()
|
||||
std::string AuraKeyboardController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string AuraMouseController::GetDeviceLocation()
|
||||
std::string AuraMouseController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -42,7 +42,12 @@ std::string AuraUSBController::GetDeviceName()
|
||||
std::string AuraUSBController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define AURA_ROG_STRIX_FLARE_PNK_LTD_PID 0x18CF
|
||||
#define AURA_ROG_CHAKRAM_WIRELESS_PID 0x18E5
|
||||
#define AURA_ROG_CHAKRAM_WIRED_1_PID 0x18E3
|
||||
#define AURA_ROG_STRIX_SCOPE_TKL_PID 0x190C
|
||||
#define AURA_ROG_CHAKRAM_WIRED_2_PID 0x1958
|
||||
|
||||
void DetectAsusAuraUSBTerminal(hid_device_info* info, const std::string& name)
|
||||
@@ -117,4 +118,5 @@ REGISTER_HID_DETECTOR_IP("ASUS ROG Chakram (Wireless)", DetectAsusAuraUS
|
||||
REGISTER_HID_DETECTOR_IP("Asus ROG Chakram (Wired)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_WIRED_1_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("Asus ROG Chakram (Wired)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_WIRED_2_PID, 0, 0xFF01);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_FLARE_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare PNK LTD", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_FLARE_PNK_LTD_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare PNK LTD", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_FLARE_PNK_LTD_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope TKL", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_TKL_PID, 1, 0xFF00);
|
||||
@@ -0,0 +1,276 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| CorsairCommanderCoreController.cpp |
|
||||
| |
|
||||
| Processing Code for Corsair Commander Core |
|
||||
| |
|
||||
| Jeff P. |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "CorsairCommanderCoreController.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_handle, const char* path)
|
||||
{
|
||||
dev = dev_handle;
|
||||
location = path;
|
||||
keepalive_thread_run = 1;
|
||||
controller_ready = 0;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Initialize controller |
|
||||
\*-----------------------------------------------------*/
|
||||
InitController();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Start keepalive thread |
|
||||
\*-----------------------------------------------------*/
|
||||
keepalive_thread = new std::thread(&CorsairCommanderCoreController::KeepaliveThread, this);
|
||||
}
|
||||
|
||||
CorsairCommanderCoreController::~CorsairCommanderCoreController()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Close keepalive thread |
|
||||
\*-----------------------------------------------------*/
|
||||
keepalive_thread_run = 0;
|
||||
keepalive_thread->join();
|
||||
delete keepalive_thread;
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Close HID device |
|
||||
\*-----------------------------------------------------*/
|
||||
hid_close(dev);
|
||||
}
|
||||
|
||||
void CorsairCommanderCoreController::InitController()
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Packet sequence to put controller into direct mode |
|
||||
\*-----------------------------------------------------*/
|
||||
unsigned char buffarray[][5] =
|
||||
{
|
||||
{0x08, 0x01, 0x03, 0x00, 0x02},
|
||||
{0x08, 0x0D, 0x00, 0x22, 0x00},
|
||||
};
|
||||
|
||||
SendMultiPkt(buffarray, sizeof(buffarray) / sizeof(buffarray[0]), sizeof(buffarray)[0] / sizeof(buffarray[0][0]));
|
||||
SetFanMode();
|
||||
}
|
||||
|
||||
std::string CorsairCommanderCoreController::GetLocationString()
|
||||
{
|
||||
return("HID: " + location);
|
||||
}
|
||||
|
||||
void CorsairCommanderCoreController::KeepaliveThread()
|
||||
{
|
||||
while(keepalive_thread_run.load())
|
||||
{
|
||||
if (controller_ready)
|
||||
{
|
||||
if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(10))
|
||||
{
|
||||
SendCommit();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
}
|
||||
|
||||
void CorsairCommanderCoreController::SendCommit()
|
||||
{
|
||||
if(!lastcolors.empty())
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| If colors remain to be sent, send them |
|
||||
\*-----------------------------------------------------*/
|
||||
SetDirectColor(lastcolors, lastzones);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char usb_buf[1025];
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Zero out buffer |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0x00, sizeof(usb_buf));
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Update last commit time |
|
||||
\*-----------------------------------------------------*/
|
||||
last_commit_time = std::chrono::steady_clock::now();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Set up Commit packet |
|
||||
\*-----------------------------------------------------*/
|
||||
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = 0x08;
|
||||
usb_buf[2] = 0x06;
|
||||
usb_buf[4] = 0xBD;
|
||||
usb_buf[5] = 0x02;
|
||||
usb_buf[8] = 0x12;
|
||||
|
||||
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CorsairCommanderCoreController::SendMultiPkt(unsigned char buffarray[][5], int r, int c)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| Private function to send multiple packets |
|
||||
\*---------------------------------------------------------*/
|
||||
unsigned char* hidtemp = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE];
|
||||
|
||||
for(unsigned int i = 0; i < r; i++)
|
||||
{
|
||||
memset(hidtemp, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
for(unsigned int j = 0; j < c; j++)
|
||||
{
|
||||
hidtemp[j+1] = buffarray[i][j];
|
||||
}
|
||||
|
||||
hid_write(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
hid_read(dev, hidtemp, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void CorsairCommanderCoreController::SetDirectColor
|
||||
(
|
||||
std::vector<RGBColor> colors,
|
||||
std::vector<zone> zones
|
||||
)
|
||||
{
|
||||
if(controller_ready == 1 && ((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::milliseconds(33)))
|
||||
{
|
||||
lastcolors = colors;
|
||||
lastzones = zones;
|
||||
int packet_offset = CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET;
|
||||
int led_idx = 0;
|
||||
int channel_idx = 0;
|
||||
unsigned char* usb_buf = new unsigned char[CORSAIR_COMMANDER_CORE_PACKET_SIZE];
|
||||
|
||||
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Prepare color information packet |
|
||||
\*-----------------------------------------------------*/
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = 0x08;
|
||||
usb_buf[2] = 0x06;
|
||||
usb_buf[4] = 0xBD;
|
||||
usb_buf[5] = 0x02;
|
||||
usb_buf[8] = 0x12;
|
||||
|
||||
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Add led colors |
|
||||
\*-------------------------------------------------*/
|
||||
for(unsigned int i = led_idx; i < led_idx + zones[zone_idx].leds_count; i++)
|
||||
{
|
||||
usb_buf[packet_offset] = RGBGetRValue(colors[i]);
|
||||
usb_buf[packet_offset+1] = RGBGetGValue(colors[i]);
|
||||
usb_buf[packet_offset+2] = RGBGetBValue(colors[i]);
|
||||
|
||||
packet_offset = packet_offset + 3;
|
||||
}
|
||||
|
||||
led_idx = led_idx + zones[zone_idx].leds_count;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Move offset for pump zone with less than 29 LEDs |
|
||||
\*-------------------------------------------------*/
|
||||
if(zone_idx == 0)
|
||||
{
|
||||
packet_offset = packet_offset + 3 * (29 - zones[zone_idx].leds_count);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Move offset for fans with less than 34 LEDs |
|
||||
\*-------------------------------------------------*/
|
||||
if(zone_idx != 0)
|
||||
{
|
||||
packet_offset = packet_offset + 3 * (34 - zones[zone_idx].leds_count);
|
||||
}
|
||||
|
||||
channel_idx++;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Sending a direct mode color packet resets the timeout |
|
||||
\*-----------------------------------------------------*/
|
||||
last_commit_time = std::chrono::steady_clock::now();
|
||||
|
||||
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void CorsairCommanderCoreController::SetFanMode()
|
||||
{
|
||||
/*--------------------------------------------------------------------------------------------------*\
|
||||
| Force controller to 6 QL fan mode to expose maximum number of LEDs per rgb port (34 LEDs per port) |
|
||||
\*--------------------------------------------------------------------------------------------------*/
|
||||
|
||||
unsigned char usb_buf[1025];
|
||||
|
||||
unsigned char buffarray4[][5] =
|
||||
{
|
||||
{0x08, 0x05, 0x01, 0x01, 0x00},
|
||||
{0x08, 0x0D, 0x01, 0x1E, 0x00},
|
||||
{0x08, 0x09, 0x01, 0x00, 0x00}
|
||||
};
|
||||
|
||||
SendMultiPkt(buffarray4, sizeof(buffarray4) / sizeof(buffarray4[0]), sizeof(buffarray4)[0] / sizeof(buffarray4[0][0]));
|
||||
|
||||
memset(usb_buf, 0, sizeof(usb_buf));
|
||||
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = 0x08;
|
||||
usb_buf[2] = 0x06;
|
||||
usb_buf[3] = 0x01;
|
||||
usb_buf[4] = 0x11;
|
||||
usb_buf[8] = 0x0D;
|
||||
usb_buf[10] = 0x07;
|
||||
usb_buf[11] = 0x01;
|
||||
usb_buf[12] = 0x08;
|
||||
|
||||
for(unsigned int i = 13; i < 25; i = i + 2)
|
||||
{
|
||||
usb_buf[i] = 0x01;
|
||||
usb_buf[i + 1] = 0x06;
|
||||
}
|
||||
|
||||
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
unsigned char buffarray2[][5] =
|
||||
{
|
||||
{0x08, 0x05, 0x01, 0x01, 0x00},
|
||||
{0x08, 0x15, 0x01, 0x00, 0x00}
|
||||
};
|
||||
|
||||
SendMultiPkt(buffarray2, sizeof(buffarray2) / sizeof(buffarray2[0]), sizeof(buffarray2)[0] / sizeof(buffarray2[0][0]));
|
||||
|
||||
memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
usb_buf[0] = 0x00;
|
||||
usb_buf[1] = 0x08;
|
||||
usb_buf[2] = 0x06;
|
||||
usb_buf[4] = 0xBD;
|
||||
usb_buf[5] = 0x02;
|
||||
usb_buf[8] = 0x12;
|
||||
|
||||
hid_write(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
hid_read(dev, usb_buf, CORSAIR_COMMANDER_CORE_PACKET_SIZE);
|
||||
|
||||
controller_ready = 1;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| CorsairCommanderCoreController.h |
|
||||
| |
|
||||
| Definitions for Corsair Commander Core |
|
||||
| Based on code by: |
|
||||
| Adam Honse ([email protected]), 8/17/2020 |
|
||||
| |
|
||||
| Jeff P. |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController.h"
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#define CORSAIR_COMMANDER_CORE_PACKET_SIZE 1025
|
||||
#define CORSAIR_COMMANDER_CORE_PREAMBLE_OFFSET 10
|
||||
#define CORSAIR_ELITE_CAPELLIX_PUMP_LED_OFFSET 87
|
||||
#define CORSAIR_QL_FAN_ZONE_OFFSET 102
|
||||
#define CORSAIR_COMMANDER_CORE_NUM_CHANNELS 6
|
||||
|
||||
enum
|
||||
{
|
||||
CORSAIR_COMMANDER_CORE_MODE_DIRECT = 0x00,
|
||||
};
|
||||
|
||||
class CorsairCommanderCoreController
|
||||
{
|
||||
public:
|
||||
CorsairCommanderCoreController(hid_device* dev_handle, const char* path);
|
||||
~CorsairCommanderCoreController();
|
||||
|
||||
std::string GetLocationString();
|
||||
|
||||
void SetDirectColor
|
||||
(
|
||||
std::vector<RGBColor>,
|
||||
std::vector<zone>
|
||||
);
|
||||
|
||||
void KeepaliveThread();
|
||||
void SetFanMode();
|
||||
|
||||
private:
|
||||
hid_device* dev;
|
||||
std::thread* keepalive_thread;
|
||||
std::atomic<bool> keepalive_thread_run;
|
||||
std::atomic<bool> controller_ready;
|
||||
std::string location;
|
||||
std::vector<RGBColor> lastcolors;
|
||||
std::vector<zone> lastzones;
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_commit_time;
|
||||
|
||||
void SendMultiPkt
|
||||
(
|
||||
unsigned char buffarray[][5],
|
||||
int r,
|
||||
int c
|
||||
);
|
||||
|
||||
void SendCommit();
|
||||
void InitController();
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "Detector.h"
|
||||
#include "CorsairCommanderCoreController.h"
|
||||
#include "RGBController.h"
|
||||
#include "RGBController_CorsairCommanderCore.h"
|
||||
#include <vector>
|
||||
#include <hidapi/hidapi.h>
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Corsair vendor ID |
|
||||
\*-----------------------------------------------------*/
|
||||
#define CORSAIR_VID 0x1B1C
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Commander Core product IDs |
|
||||
\*-----------------------------------------------------*/
|
||||
#define CORSAIR_H150I_COMMANDER_CORE_PID 0x0C1C
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectCorsairCapellixControllers *
|
||||
* *
|
||||
* Tests the USB address to see if a Corsair RGB Cooler controller exists there. *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectCorsairCapellixHIDControllers(hid_device_info* info, const std::string& name)
|
||||
{
|
||||
hid_device* dev = hid_open_path(info->path);
|
||||
|
||||
if(dev)
|
||||
{
|
||||
CorsairCommanderCoreController* controller = new CorsairCommanderCoreController(dev, info->path);
|
||||
RGBController_CorsairCommanderCore* rgb_controller = new RGBController_CorsairCommanderCore(controller);
|
||||
|
||||
rgb_controller->name = name;
|
||||
|
||||
ResourceManager::get()->RegisterRGBController(rgb_controller);
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_HID_DETECTOR_PU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_H150I_COMMANDER_CORE_PID, 0xFF42, 0x01);
|
||||
@@ -0,0 +1,125 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_CorsairCapellix.cpp |
|
||||
| |
|
||||
| Generic RGB Interface for Corsair |
|
||||
| Commander Core |
|
||||
| |
|
||||
| Jeff P. |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "RGBController_CorsairCommanderCore.h"
|
||||
|
||||
RGBController_CorsairCommanderCore::RGBController_CorsairCommanderCore(CorsairCommanderCoreController* corsair_ptr)
|
||||
{
|
||||
corsair = corsair_ptr;
|
||||
|
||||
vendor = "Corsair";
|
||||
description = "Corsair Commander Core";
|
||||
type = DEVICE_TYPE_COOLER;
|
||||
location = corsair->GetLocationString();
|
||||
|
||||
SetupZones();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
}
|
||||
|
||||
RGBController_CorsairCommanderCore::~RGBController_CorsairCommanderCore()
|
||||
{
|
||||
delete corsair;
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::SetupZones()
|
||||
{
|
||||
std::atomic<bool> first_run;
|
||||
first_run = 0;
|
||||
|
||||
if(zones.size() == 0)
|
||||
{
|
||||
first_run = 1;
|
||||
}
|
||||
|
||||
zones.resize(7);
|
||||
zones[0].name = "Pump";
|
||||
zones[0].type = ZONE_TYPE_LINEAR;
|
||||
zones[0].leds_min = 0;
|
||||
zones[0].leds_max = 29;
|
||||
|
||||
for(unsigned int i = 1; i < (CORSAIR_COMMANDER_CORE_NUM_CHANNELS + 1); i++)
|
||||
{
|
||||
zones[i].name = "RGB Port " + std::to_string(i);
|
||||
zones[i].type = ZONE_TYPE_LINEAR;
|
||||
zones[i].leds_min = 0;
|
||||
zones[i].leds_max = 34;
|
||||
|
||||
if(first_run)
|
||||
{
|
||||
zones[i].leds_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
leds.clear();
|
||||
colors.clear();
|
||||
|
||||
for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++)
|
||||
{
|
||||
for (unsigned int led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = zones[zone_idx].name + " LED " + std::to_string(led_idx+1);
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::ResizeZone(int zone, int new_size)
|
||||
{
|
||||
if((size_t) zone >= zones.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max))
|
||||
{
|
||||
zones[zone].leds_count = new_size;
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::DeviceUpdateLEDs()
|
||||
{
|
||||
DeviceUpdateMode();
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::SetCustomMode()
|
||||
{
|
||||
active_mode = 0;
|
||||
}
|
||||
|
||||
void RGBController_CorsairCommanderCore::DeviceUpdateMode()
|
||||
{
|
||||
switch(modes[active_mode].value)
|
||||
{
|
||||
case CORSAIR_COMMANDER_CORE_MODE_DIRECT:
|
||||
corsair->SetDirectColor(colors, zones);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_CorsairCapellix.h |
|
||||
| |
|
||||
| Generic RGB Interface for Corsair |
|
||||
| Commander Core |
|
||||
| |
|
||||
| Jeff P. |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "RGBController.h"
|
||||
#include "CorsairCommanderCoreController.h"
|
||||
|
||||
class RGBController_CorsairCommanderCore : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_CorsairCommanderCore(CorsairCommanderCoreController* corsair_ptr);
|
||||
~RGBController_CorsairCommanderCore();
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void SetCustomMode();
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
CorsairCommanderCoreController* corsair;
|
||||
std::vector<int> fanleds{0};
|
||||
};
|
||||
@@ -64,7 +64,12 @@ std::string CorsairLightingNodeController::GetLocationString()
|
||||
std::string CorsairLightingNodeController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,12 @@ std::string CorsairPeripheralController::GetName()
|
||||
std::string CorsairPeripheralController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
@@ -232,7 +237,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 +374,7 @@ void CorsairPeripheralController::LightingControl()
|
||||
| Probably a key mapping packet? |
|
||||
\*-----------------------------------------------------*/
|
||||
|
||||
void CorsairPeripheralController::SetupK95LightingControl()
|
||||
void CorsairPeripheralController::SetupK55AndK95LightingControl()
|
||||
{
|
||||
char usb_buf[65];
|
||||
|
||||
@@ -535,7 +539,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);
|
||||
|
||||
@@ -51,7 +51,12 @@ std::string CorsairWirelessController::GetName()
|
||||
std::string CorsairWirelessController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -38,7 +38,7 @@ std::string DasKeyboardController::GetSerialString()
|
||||
int err = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
std::string return_string;
|
||||
if(!err)
|
||||
if(err == 0)
|
||||
{
|
||||
std::wstring return_wstring = serial_string;
|
||||
return_string = std::string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -31,7 +31,12 @@ std::string DuckyKeyboardController::GetDeviceLocation()
|
||||
std::string DuckyKeyboardController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -33,7 +33,12 @@ std::string EVisionKeyboardController::GetDeviceLocation()
|
||||
std::string EVisionKeyboardController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string ATC800Controller::GetDeviceLocation()
|
||||
std::string ATC800Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -36,6 +36,15 @@ void RGBFusionGPUController::SetColor(unsigned char red, unsigned char green, un
|
||||
bus->i2c_smbus_write_byte(dev, red);
|
||||
bus->i2c_smbus_write_byte(dev, green);
|
||||
bus->i2c_smbus_write_byte(dev, blue);
|
||||
|
||||
// Pad commands with 4 zero-bytes for NVIDIA_RTX3060_DEV
|
||||
if (dev == 0x62)
|
||||
{
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
void RGBFusionGPUController::SetMode(unsigned char mode, unsigned char speed)
|
||||
@@ -44,4 +53,13 @@ void RGBFusionGPUController::SetMode(unsigned char mode, unsigned char speed)
|
||||
bus->i2c_smbus_write_byte(dev, mode);
|
||||
bus->i2c_smbus_write_byte(dev, speed);
|
||||
bus->i2c_smbus_write_byte(dev, 0x63);
|
||||
|
||||
// Pad commands with 4 zero-bytes for NVIDIA_RTX3060_DEV
|
||||
if (dev == 0x62)
|
||||
{
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
bus->i2c_smbus_write_byte(dev, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -34,14 +34,16 @@ static const gpu_pci_device device_list[] =
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1650_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1650_GAMING_OC_SUB_DEV, 0x55, "Gigabyte GTX1650 Gaming OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_GTX1660S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660S_GAMING_OC_SUB_DEV, 0x47, "Gigabyte GTX1660 SUPER Gaming OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_SUB_DEV, 0x47, "Gigabyte RTX2060 Gaming OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_SUB_DEV, 0x47, "Gigabyte RTX2060 SUPER Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV, 0x47, "Gigabyte RTX2060 Gaming OC PRO" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_SUB_DEV, 0x47, "Gigabyte RTX2060 SUPER Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_SUB_DEV, 0x47, "Gigabyte RTX2070 Gaming OC 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_WINDFORCE_SUB_DEV, 0x47, "Gigabyte RTX2070 Windforce 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_SUB_DEV, 0x47, "Gigabyte RTX2070S Gaming OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_SUB_DEV, 0x55, "Gigabyte RTX2070S Gaming OC 3X" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_GAMING_OC_SUB_DEV, 0x47, "Gigabyte RTX2080 Gaming OC 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_A_GAMING_OC_SUB_DEV, 0x47, "Gigabyte RTX2080 Gaming OC 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63, "Gigabyte RTX3060 EAGLE OC 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62, "Gigabyte RTX3060 Gaming OC 12G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63, "Gigabyte RTX3060 Ti EAGLE OC 8G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_VISION_OC_SUB_DEV, 0x63, "Gigabyte RTX3070 Vision 8G" },
|
||||
};
|
||||
|
||||
@@ -67,6 +69,15 @@ bool TestForGigabyteRGBFusionGPUController(i2c_smbus_interface* bus, unsigned ch
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
|
||||
// NVIDIA_RTX3060_DEV requires additional bytes to initialise
|
||||
if (address == 0x62)
|
||||
{
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
bus->i2c_smbus_write_byte(address, 0x00);
|
||||
}
|
||||
|
||||
pass = true;
|
||||
|
||||
|
||||
@@ -29,7 +29,12 @@ std::string HoltekA070Controller::GetDeviceLocation()
|
||||
std::string HoltekA070Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string HoltekA1FAController::GetDeviceLocation()
|
||||
std::string HoltekA1FAController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -35,7 +35,12 @@ std::string HyperXAlloyElite2Controller::GetDeviceLocation()
|
||||
std::string HyperXAlloyElite2Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -33,7 +33,12 @@ std::string HyperXAlloyOriginsController::GetDeviceLocation()
|
||||
std::string HyperXAlloyOriginsController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -46,7 +46,12 @@ std::string HyperXKeyboardController::GetDeviceLocation()
|
||||
std::string HyperXKeyboardController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string HyperXPulsefireDartController::GetDeviceLocation()
|
||||
std::string HyperXPulsefireDartController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string HyperXPulsefireFPSProController::GetDeviceLocation()
|
||||
std::string HyperXPulsefireFPSProController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string HyperXPulsefireSurgeController::GetDeviceLocation()
|
||||
std::string HyperXPulsefireSurgeController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -30,7 +30,12 @@ std::string HyperXMousematController::GetDeviceLocation()
|
||||
std::string HyperXMousematController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -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,69 +441,14 @@ 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);
|
||||
}
|
||||
addLogitechLightsyncMouse1zone(info, name, 0xFF, 0x0E, 0x3C);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
@@ -529,27 +487,185 @@ 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 G502 Proteus Spectrum Gaming Mouse", DetectLogitechMouseG502PS, LOGITECH_VID, LOGITECH_G502_PROTEUS_SPECTRUM_PID, 1, 0xFF00);
|
||||
REGISTER_HID_DETECTOR_IP ("Logitech G502 Hero Gaming Mouse", DetectLogitechMouseG502PS, LOGITECH_VID, LOGITECH_G502_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_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_LIGHTSPEED_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
|
||||
|
||||
@@ -21,7 +21,12 @@ std::string LogitechG203LController::GetDeviceLocation()
|
||||
std::string LogitechG203LController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -28,7 +28,12 @@ std::string LogitechG213Controller::GetDeviceLocation()
|
||||
std::string LogitechG213Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -25,7 +25,12 @@ LogitechG810Controller::~LogitechG810Controller()
|
||||
std::string LogitechG810Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -24,7 +24,12 @@ LogitechG815Controller::~LogitechG815Controller()
|
||||
std::string LogitechG815Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -25,7 +25,12 @@ LogitechG910Controller::~LogitechG910Controller()
|
||||
std::string LogitechG910Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev_pkt_0x11, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -46,7 +46,12 @@ std::string LogitechGLightsyncController::GetDeviceLocation()
|
||||
std::string LogitechGLightsyncController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*-----------------------------------------*\
|
||||
| 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];
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -21,7 +21,7 @@ static unsigned int matrix_map[7][27] =
|
||||
{ NA, NA, 37, NA, 54, 55, 56, 57, NA, 58, 59, 60, 61, NA, 62, 63, 64, 65, NA, 66, 67, 68, NA, 106, 107, 108, 109 },
|
||||
{ 112, NA, 49, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, NA, 41, 42, 38, NA, NA, 69, 70, 71, NA, 79, 80, 81, 82 },
|
||||
{ 113, NA, 39, NA, 16, 22, 4, 17, NA, 19, 24, 20, 8, 14, 15, 43, 44, 45, NA, 72, 73, 74, NA, 91, 92, 93, 83 },
|
||||
{ 114, NA, 53, NA, 0, 18, 3, 5, NA, 6, 7, 9, 10, 11, 47, 48, 36, NA, NA, NA, NA, NA, NA, 88, 89, 90, NA },
|
||||
{ 114, NA, 53, NA, 0, 18, 3, 5, NA, 6, 7, 9, 10, 11, 47, 48, 46, 36, NA, NA, NA, NA, NA, 88, 89, 90, NA },
|
||||
{ 115, NA, 99, NA, 25, 23, 2, 21, NA, 1, NA, 13, 12, 50, 51, 52, 103, NA, NA, NA, 78, NA, NA, 85, 86, 87, 84 },
|
||||
{ 116, NA, 98, 101, 100, NA, NA, NA, NA, 40, NA, NA, NA, NA, 104, 105, 97, 102, NA, 76, 77, 75, NA, 94, NA, 95, NA } };
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -35,7 +35,12 @@ std::string MSI3ZoneController::GetDeviceLocation()
|
||||
std::string MSI3ZoneController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -36,8 +36,8 @@ static const msi_gpu_pci_device device_list[] =
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, "MSI GeForce RTX 2060 Gaming Z 6G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, "MSI GeForce RTX 2060 Gaming Z 6G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV_2, "MSI GeForce RTX 2060 Gaming Z 6G" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_DEV, MSI_SUB_VEN, MSI_RTX2060S_GAMING_X_SUB_DEV, "MSI GeForce RTX 2060 Super Gaming X" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_DEV, MSI_SUB_VEN, MSI_RTX2060S_ARMOR_OC_SUB_DEV, "MSI GeForce RTX 2060 Super ARMOR OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_GAMING_X_SUB_DEV, "MSI GeForce RTX 2060 Super Gaming X" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_ARMOR_OC_SUB_DEV, "MSI GeForce RTX 2060 Super ARMOR OC" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_Z_SUB_DEV, "MSI GeForce RTX 2070 Gaming Z" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_SUB_DEV, "MSI GeForce RTX 2070 Gaming" },
|
||||
{ NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_ARMOR_SUB_DEV, "MSI GeForce RTX 2070 ARMOR" },
|
||||
|
||||
@@ -71,7 +71,12 @@ std::string NZXTHue2Controller::GetFirmwareVersion()
|
||||
std::string NZXTHue2Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -56,7 +56,12 @@ std::string NZXTKrakenController::GetLocation()
|
||||
std::string NZXTKrakenController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| Driver for Philips Hue |
|
||||
| |
|
||||
| Adam Honse ([email protected]), 9/15/2020 |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "PhilipsHueController.h"
|
||||
|
||||
PhilipsHueController::PhilipsHueController(hueplusplus::Light& light_ptr, std::string bridge_ip):light(light_ptr)
|
||||
{
|
||||
dark = false;
|
||||
location = "IP: " + bridge_ip;
|
||||
}
|
||||
|
||||
PhilipsHueController::~PhilipsHueController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string PhilipsHueController::GetLocation()
|
||||
{
|
||||
return(location);
|
||||
}
|
||||
|
||||
std::string PhilipsHueController::GetName()
|
||||
{
|
||||
return(light.getModelId());
|
||||
}
|
||||
|
||||
std::string PhilipsHueController::GetVersion()
|
||||
{
|
||||
return(light.getSwVersion());
|
||||
}
|
||||
|
||||
std::string PhilipsHueController::GetManufacturer()
|
||||
{
|
||||
return(light.getManufacturername());
|
||||
}
|
||||
|
||||
std::string PhilipsHueController::GetUniqueID()
|
||||
{
|
||||
return(light.getUId());
|
||||
}
|
||||
|
||||
void PhilipsHueController::SetColor(unsigned char red, unsigned char green, unsigned char blue)
|
||||
{
|
||||
hueplusplus::RGB rgb;
|
||||
rgb.r = red;
|
||||
rgb.g = green;
|
||||
rgb.b = blue;
|
||||
|
||||
if((red == 0) && (green == 0) && (blue == 0))
|
||||
{
|
||||
if(!dark)
|
||||
{
|
||||
try
|
||||
{
|
||||
light.setColorRGB(rgb, 0);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dark = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
dark = false;
|
||||
|
||||
try
|
||||
{
|
||||
light.setColorRGB(rgb, 0);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| Definitions for Philips Hue |
|
||||
| |
|
||||
| Adam Honse ([email protected]), 9/15/2020 |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "HueDeviceTypes.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#pragma once
|
||||
|
||||
class PhilipsHueController
|
||||
{
|
||||
public:
|
||||
PhilipsHueController(hueplusplus::Light& light_ptr, std::string bridge_ip);
|
||||
~PhilipsHueController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetVersion();
|
||||
std::string GetManufacturer();
|
||||
std::string GetUniqueID();
|
||||
|
||||
void SetColor(unsigned char red, unsigned char green, unsigned char blue);
|
||||
|
||||
private:
|
||||
hueplusplus::Light& light;
|
||||
std::string location;
|
||||
bool dark;
|
||||
};
|
||||
@@ -0,0 +1,232 @@
|
||||
#include "Bridge.h"
|
||||
#include "HueDeviceTypes.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "WinHttpHandler.h"
|
||||
#else
|
||||
#include "LinHttpHandler.h"
|
||||
#endif
|
||||
|
||||
#include "Detector.h"
|
||||
#include "LogManager.h"
|
||||
#include "PhilipsHueController.h"
|
||||
#include "PhilipsHueEntertainmentController.h"
|
||||
#include "RGBController_PhilipsHue.h"
|
||||
#include "RGBController_PhilipsHueEntertainment.h"
|
||||
#include "SettingsManager.h"
|
||||
|
||||
/******************************************************************************************\
|
||||
* *
|
||||
* DetectPhilipsHueControllers *
|
||||
* *
|
||||
* Detect Philips Hue lighting devices with RGB control *
|
||||
* *
|
||||
\******************************************************************************************/
|
||||
|
||||
void DetectPhilipsHueControllers(std::vector<RGBController*>& rgb_controllers)
|
||||
{
|
||||
json hue_settings;
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Create an HTTP handler |
|
||||
\*-------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
using SystemHttpHandler = hueplusplus::WinHttpHandler;
|
||||
#else
|
||||
using SystemHttpHandler = hueplusplus::LinHttpHandler;
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Get Philips Hue settings from settings manager |
|
||||
\*-------------------------------------------------*/
|
||||
hue_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("PhilipsHueDevices");
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Create a finder and find bridges |
|
||||
\*-------------------------------------------------*/
|
||||
static hueplusplus::BridgeFinder finder(std::make_shared<SystemHttpHandler>());
|
||||
std::vector<hueplusplus::BridgeFinder::BridgeIdentification> bridges;// = finder.findBridges();
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If no bridges were detected, manually add bridge |
|
||||
| IP and MAC (need to get these from file) |
|
||||
\*-------------------------------------------------*/
|
||||
if(bridges.empty())
|
||||
{
|
||||
if(hue_settings.contains("bridges"))
|
||||
{
|
||||
hueplusplus::BridgeFinder::BridgeIdentification ident;
|
||||
|
||||
if(hue_settings["bridges"][0].contains("ip"))
|
||||
{
|
||||
ident.ip = hue_settings["bridges"][0]["ip"];
|
||||
}
|
||||
|
||||
if(hue_settings["bridges"][0].contains("mac"))
|
||||
{
|
||||
ident.mac = hue_settings["bridges"][0]["mac"];
|
||||
}
|
||||
|
||||
bridges.push_back(ident);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If no bridges were found, return, otherwise |
|
||||
| connect to the first bridge |
|
||||
\*-------------------------------------------------*/
|
||||
if(bridges.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Check if a saved username exists |
|
||||
\*-------------------------------------------------*/
|
||||
if(hue_settings.contains("bridges"))
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Add the username if it exists |
|
||||
\*-------------------------------------------------*/
|
||||
if(hue_settings["bridges"][0].contains("username"))
|
||||
{
|
||||
finder.addUsername(bridges[0].mac, hue_settings["bridges"][0]["username"]);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Add the client key if it exists |
|
||||
\*-------------------------------------------------*/
|
||||
if(hue_settings["bridges"][0].contains("clientkey"))
|
||||
{
|
||||
finder.addClientKey(bridges[0].mac, hue_settings["bridges"][0]["clientkey"]);
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| If username was added, this should connect right |
|
||||
| away. If not, the user will have to push the |
|
||||
| connect button on the bridge. |
|
||||
\*-------------------------------------------------*/
|
||||
try
|
||||
{
|
||||
static hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
|
||||
|
||||
bridge.refresh();
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Check to see if we need to save the settings |
|
||||
| Settings need to be saved if either username or |
|
||||
| client key either do not exist or have changed |
|
||||
\*-------------------------------------------------*/
|
||||
bool save_settings = false;
|
||||
bool use_entertainment = false;
|
||||
|
||||
if(hue_settings.contains("bridges"))
|
||||
{
|
||||
if(hue_settings["bridges"][0].contains("username"))
|
||||
{
|
||||
if(hue_settings["bridges"][0]["username"] != bridge.getUsername())
|
||||
{
|
||||
save_settings = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
save_settings = true;
|
||||
}
|
||||
|
||||
if(hue_settings["bridges"][0].contains("clientkey"))
|
||||
{
|
||||
if(hue_settings["bridges"][0]["clientkey"] != bridge.getClientKey())
|
||||
{
|
||||
use_entertainment = true;
|
||||
save_settings = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
save_settings = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Save the settings if needed |
|
||||
\*-------------------------------------------------*/
|
||||
if(save_settings)
|
||||
{
|
||||
hue_settings["bridges"][0]["username"] = bridge.getUsername();
|
||||
hue_settings["bridges"][0]["clientkey"] = bridge.getClientKey();
|
||||
hue_settings["bridges"][0]["entertainment"] = use_entertainment;
|
||||
|
||||
ResourceManager::get()->GetSettingsManager()->SetSettings("PhilipsHueDevices", hue_settings);
|
||||
|
||||
ResourceManager::get()->GetSettingsManager()->SaveSettings();
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Get all groups from the bridge |
|
||||
\*-------------------------------------------------*/
|
||||
if(hue_settings["bridges"][0].contains("entertainment"))
|
||||
{
|
||||
use_entertainment = hue_settings["bridges"][0]["entertainment"];
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Get all groups from the bridge |
|
||||
\*-------------------------------------------------*/
|
||||
if(use_entertainment)
|
||||
{
|
||||
std::vector<hueplusplus::Group> groups = bridge.groups().getAll();
|
||||
|
||||
if(groups.size() > 0)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Loop through all available groups and check to |
|
||||
| see if any are Entertainment groups |
|
||||
\*-------------------------------------------------*/
|
||||
for(unsigned int group_idx = 0; group_idx < groups.size(); group_idx++)
|
||||
{
|
||||
if(groups[group_idx].getType() == "Entertainment")
|
||||
{
|
||||
PhilipsHueEntertainmentController* new_controller = new PhilipsHueEntertainmentController(bridge, groups[group_idx]);
|
||||
RGBController_PhilipsHueEntertainment* new_rgbcontroller = new RGBController_PhilipsHueEntertainment(new_controller);
|
||||
rgb_controllers.push_back(new_rgbcontroller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Get all lights from the bridge |
|
||||
\*-------------------------------------------------*/
|
||||
else
|
||||
{
|
||||
std::vector<hueplusplus::Light> lights = bridge.lights().getAll();
|
||||
|
||||
if(lights.size() > 0)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Loop through all available lights and add those |
|
||||
| that have color (RGB) control capability |
|
||||
\*-------------------------------------------------*/
|
||||
for(unsigned int light_idx = 0; light_idx < lights.size(); light_idx++)
|
||||
{
|
||||
if(lights[light_idx].hasColorControl())
|
||||
{
|
||||
PhilipsHueController* new_controller = new PhilipsHueController(lights[light_idx], bridge.getBridgeIP());
|
||||
RGBController_PhilipsHue* new_rgbcontroller = new RGBController_PhilipsHue(new_controller);
|
||||
rgb_controllers.push_back(new_rgbcontroller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
LOG_NOTICE("Exception occurred in Philips Hue detection");
|
||||
}
|
||||
}
|
||||
} /* DetectPhilipsHueControllers() */
|
||||
|
||||
REGISTER_DETECTOR("Philips Hue", DetectPhilipsHueControllers);
|
||||
@@ -0,0 +1,82 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| Driver for Philips Hue Entertainment Mode |
|
||||
| |
|
||||
| Adam Honse ([email protected]), 11/6/2020 |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "PhilipsHueEntertainmentController.h"
|
||||
|
||||
PhilipsHueEntertainmentController::PhilipsHueEntertainmentController(hueplusplus::Bridge& bridge_ptr, hueplusplus::Group& group_ptr):bridge(bridge_ptr),group(group_ptr)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Fill in location string with bridge IP |
|
||||
\*-------------------------------------------------*/
|
||||
location = "IP: " + bridge.getBridgeIP();
|
||||
num_leds = group.getLightIds().size();
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Create Entertainment Mode from bridge and group |
|
||||
\*-------------------------------------------------*/
|
||||
entertainment = new hueplusplus::EntertainmentMode(bridge, group);
|
||||
|
||||
/*-------------------------------------------------*\
|
||||
| Connect Hue Entertainment Mode |
|
||||
\*-------------------------------------------------*/
|
||||
entertainment->connect();
|
||||
}
|
||||
|
||||
PhilipsHueEntertainmentController::~PhilipsHueEntertainmentController()
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Disconnect Hue Entertainment Mode |
|
||||
\*-------------------------------------------------*/
|
||||
entertainment->disconnect();
|
||||
}
|
||||
|
||||
std::string PhilipsHueEntertainmentController::GetLocation()
|
||||
{
|
||||
return(location);
|
||||
}
|
||||
|
||||
std::string PhilipsHueEntertainmentController::GetName()
|
||||
{
|
||||
return(group.getName());
|
||||
}
|
||||
|
||||
std::string PhilipsHueEntertainmentController::GetVersion()
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string PhilipsHueEntertainmentController::GetManufacturer()
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::string PhilipsHueEntertainmentController::GetUniqueID()
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
unsigned int PhilipsHueEntertainmentController::GetNumLEDs()
|
||||
{
|
||||
return(num_leds);
|
||||
}
|
||||
|
||||
void PhilipsHueEntertainmentController::SetColor(RGBColor* colors)
|
||||
{
|
||||
/*-------------------------------------------------*\
|
||||
| Fill in Entertainment Mode light data |
|
||||
\*-------------------------------------------------*/
|
||||
for(unsigned int light_idx = 0; light_idx < num_leds; light_idx++)
|
||||
{
|
||||
RGBColor color = colors[light_idx];
|
||||
unsigned char red = RGBGetRValue(color);
|
||||
unsigned char green = RGBGetGValue(color);
|
||||
unsigned char blue = RGBGetBValue(color);
|
||||
|
||||
entertainment->setColorRGB(light_idx, red, green, blue);
|
||||
}
|
||||
|
||||
entertainment->update();
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*---------------------------------------------------------*\
|
||||
| Definitions for Philips Hue Entertainment Mode |
|
||||
| |
|
||||
| Adam Honse ([email protected]), 11/6/2020 |
|
||||
\*---------------------------------------------------------*/
|
||||
|
||||
#include "RGBController.h"
|
||||
#include "Bridge.h"
|
||||
#include "EntertainmentMode.h"
|
||||
#include "Group.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#pragma once
|
||||
|
||||
#define HUE_ENTERTAINMENT_HEADER_SIZE 16
|
||||
#define HUE_ENTERTAINMENT_LIGHT_SIZE 9
|
||||
|
||||
class PhilipsHueEntertainmentController
|
||||
{
|
||||
public:
|
||||
PhilipsHueEntertainmentController(hueplusplus::Bridge& bridge_ptr, hueplusplus::Group& group_ptr);
|
||||
~PhilipsHueEntertainmentController();
|
||||
|
||||
std::string GetLocation();
|
||||
std::string GetName();
|
||||
std::string GetVersion();
|
||||
std::string GetManufacturer();
|
||||
std::string GetUniqueID();
|
||||
unsigned int GetNumLEDs();
|
||||
|
||||
void SetColor(RGBColor* colors);
|
||||
|
||||
private:
|
||||
hueplusplus::Bridge& bridge;
|
||||
hueplusplus::Group& group;
|
||||
hueplusplus::EntertainmentMode* entertainment;
|
||||
|
||||
std::string location;
|
||||
unsigned int num_leds;
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_PhilipsHue.cpp |
|
||||
| |
|
||||
| Generic RGB Interface for Philips Hue |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 9/15/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "RGBController_PhilipsHue.h"
|
||||
|
||||
RGBController_PhilipsHue::RGBController_PhilipsHue(PhilipsHueController* light_ptr)
|
||||
{
|
||||
light = light_ptr;
|
||||
|
||||
name = light->GetManufacturer() + " " + light->GetName();
|
||||
type = DEVICE_TYPE_LIGHT;
|
||||
version = light->GetVersion();
|
||||
description = "Philips Hue Device";
|
||||
serial = light->GetUniqueID();
|
||||
location = light->GetLocation();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::SetupZones()
|
||||
{
|
||||
zone led_zone;
|
||||
led_zone.name = "RGB Light";
|
||||
led_zone.type = ZONE_TYPE_SINGLE;
|
||||
led_zone.leds_min = 1;
|
||||
led_zone.leds_max = 1;
|
||||
led_zone.leds_count = 1;
|
||||
led_zone.matrix_map = NULL;
|
||||
zones.push_back(led_zone);
|
||||
|
||||
led new_led;
|
||||
new_led.name = "RGB Light";
|
||||
|
||||
leds.push_back(new_led);
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::DeviceUpdateLEDs()
|
||||
{
|
||||
unsigned char red = RGBGetRValue(colors[0]);
|
||||
unsigned char grn = RGBGetGValue(colors[0]);
|
||||
unsigned char blu = RGBGetBValue(colors[0]);
|
||||
|
||||
light->SetColor(red, grn, blu);
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::SetCustomMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHue::DeviceUpdateMode()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_PhilipsHue.h |
|
||||
| |
|
||||
| Generic RGB Interface for Philips Hue |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 9/15/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "RGBController.h"
|
||||
#include "PhilipsHueController.h"
|
||||
|
||||
class RGBController_PhilipsHue : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_PhilipsHue(PhilipsHueController* light_ptr);
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void SetCustomMode();
|
||||
void DeviceUpdateMode();
|
||||
|
||||
private:
|
||||
PhilipsHueController* light;
|
||||
};
|
||||
@@ -0,0 +1,113 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_PhilipsHueEntertainment.cpp|
|
||||
| |
|
||||
| Generic RGB Interface for Philips Hue |
|
||||
| Entertainment Mode |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 11/7/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#include "RGBController_PhilipsHueEntertainment.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
RGBController_PhilipsHueEntertainment::RGBController_PhilipsHueEntertainment(PhilipsHueEntertainmentController* light_ptr)
|
||||
{
|
||||
light = light_ptr;
|
||||
|
||||
name = light->GetManufacturer() + " " + light->GetName();
|
||||
type = DEVICE_TYPE_LIGHT;
|
||||
version = light->GetVersion();
|
||||
description = "Philips Hue Entertainment Mode Device";
|
||||
serial = light->GetUniqueID();
|
||||
location = light->GetLocation();
|
||||
|
||||
mode Direct;
|
||||
Direct.name = "Direct";
|
||||
Direct.value = 0;
|
||||
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
|
||||
Direct.color_mode = MODE_COLORS_PER_LED;
|
||||
modes.push_back(Direct);
|
||||
|
||||
SetupZones();
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| The Philips Hue Entertainment Mode requires a packet |
|
||||
| within 10 seconds of sending the lighting change in |
|
||||
| order to not exit entertainment mode. Start a thread |
|
||||
| to continuously send a packet every 5s |
|
||||
\*-----------------------------------------------------*/
|
||||
KeepaliveThreadRunning = true;
|
||||
KeepaliveThread = new std::thread(&RGBController_PhilipsHueEntertainment::KeepaliveThreadFunction, this);
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::SetupZones()
|
||||
{
|
||||
zone led_zone;
|
||||
led_zone.name = "RGB Light";
|
||||
led_zone.type = ZONE_TYPE_SINGLE;
|
||||
led_zone.leds_min = light->GetNumLEDs();
|
||||
led_zone.leds_max = light->GetNumLEDs();
|
||||
led_zone.leds_count = light->GetNumLEDs();
|
||||
led_zone.matrix_map = NULL;
|
||||
zones.push_back(led_zone);
|
||||
|
||||
for(unsigned int led_idx = 0; led_idx < light->GetNumLEDs(); led_idx++)
|
||||
{
|
||||
led new_led;
|
||||
new_led.name = "RGB Light";
|
||||
|
||||
leds.push_back(new_led);
|
||||
}
|
||||
|
||||
SetupColors();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::ResizeZone(int /*zone*/, int /*new_size*/)
|
||||
{
|
||||
/*---------------------------------------------------------*\
|
||||
| This device does not support resizing zones |
|
||||
\*---------------------------------------------------------*/
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::DeviceUpdateLEDs()
|
||||
{
|
||||
last_update_time = std::chrono::steady_clock::now();
|
||||
|
||||
light->SetColor(&colors[0]);
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::UpdateZoneLEDs(int /*zone*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::UpdateSingleLED(int /*led*/)
|
||||
{
|
||||
DeviceUpdateLEDs();
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::SetCustomMode()
|
||||
{
|
||||
active_mode = 0;
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::DeviceUpdateMode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RGBController_PhilipsHueEntertainment::KeepaliveThreadFunction()
|
||||
{
|
||||
while(KeepaliveThreadRunning)
|
||||
{
|
||||
if(active_mode == 0)
|
||||
{
|
||||
if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::seconds(5))
|
||||
{
|
||||
UpdateLEDs();
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(1s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*-----------------------------------------*\
|
||||
| RGBController_PhilipsHueEntertainment.h |
|
||||
| |
|
||||
| Generic RGB Interface for Philips Hue |
|
||||
| Entertainment Mode |
|
||||
| |
|
||||
| Adam Honse (CalcProgrammer1) 11/7/2020 |
|
||||
\*-----------------------------------------*/
|
||||
|
||||
#pragma once
|
||||
#include "RGBController.h"
|
||||
#include "PhilipsHueEntertainmentController.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
class RGBController_PhilipsHueEntertainment : public RGBController
|
||||
{
|
||||
public:
|
||||
RGBController_PhilipsHueEntertainment(PhilipsHueEntertainmentController* light_ptr);
|
||||
|
||||
void SetupZones();
|
||||
|
||||
void ResizeZone(int zone, int new_size);
|
||||
|
||||
void DeviceUpdateLEDs();
|
||||
void UpdateZoneLEDs(int zone);
|
||||
void UpdateSingleLED(int led);
|
||||
|
||||
void SetCustomMode();
|
||||
void DeviceUpdateMode();
|
||||
|
||||
void KeepaliveThreadFunction();
|
||||
|
||||
private:
|
||||
PhilipsHueEntertainmentController* light;
|
||||
|
||||
std::atomic<bool> KeepaliveThreadRunning;
|
||||
std::thread* KeepaliveThread;
|
||||
|
||||
std::chrono::time_point<std::chrono::steady_clock> last_update_time;
|
||||
};
|
||||
@@ -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
|
||||
);
|
||||
};
|
||||
@@ -26,7 +26,12 @@ std::string RedragonM711Controller::GetDeviceLocation()
|
||||
std::string RedragonM711Controller::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -43,7 +43,12 @@ unsigned int SinowealthController::GetLEDCount()
|
||||
std::string SinowealthController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev_report_id_4, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev_report_id_4, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -41,7 +41,12 @@ std::string PoseidonZRGBController::GetDeviceLocation()
|
||||
std::string PoseidonZRGBController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -32,7 +32,12 @@ std::string ThermaltakeRiingController::GetDeviceLocation()
|
||||
std::string ThermaltakeRiingController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
@@ -74,7 +74,12 @@ std::string ZalmanZSyncController::GetLocationString()
|
||||
std::string ZalmanZSyncController::GetSerialString()
|
||||
{
|
||||
wchar_t serial_string[128];
|
||||
hid_get_serial_number_string(dev, serial_string, 128);
|
||||
int ret = hid_get_serial_number_string(dev, serial_string, 128);
|
||||
|
||||
if(ret != 0)
|
||||
{
|
||||
return("");
|
||||
}
|
||||
|
||||
std::wstring return_wstring = serial_string;
|
||||
std::string return_string(return_wstring.begin(), return_wstring.end());
|
||||
|
||||
+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
|
||||
|
||||
|
||||
+154
-1
@@ -23,7 +23,7 @@ greaterThan(QT_MAJOR_VERSION, 5): DEFINES += _QT6
|
||||
#-----------------------------------------------------------------------------------------------#
|
||||
# Application Configuration #
|
||||
#-----------------------------------------------------------------------------------------------#
|
||||
VERSION = 0.51
|
||||
VERSION = 0.61
|
||||
TARGET = OpenRGB
|
||||
TEMPLATE = app
|
||||
|
||||
@@ -49,6 +49,8 @@ DEFINES +=
|
||||
INCLUDEPATH += \
|
||||
dependencies/ColorWheel \
|
||||
dependencies/CRCpp/ \
|
||||
dependencies/hueplusplus-1.0.0/include \
|
||||
dependencies/hueplusplus-1.0.0/include/hueplusplus \
|
||||
dependencies/json/ \
|
||||
dependencies/libe131/src/ \
|
||||
dependencies/libcmmk/include/ \
|
||||
@@ -66,6 +68,7 @@ INCLUDEPATH +=
|
||||
Controllers/AsusAuraSMBusController/ \
|
||||
Controllers/AsusAuraUSBController/ \
|
||||
Controllers/CoolerMasterController/ \
|
||||
Controllers/CorsairCommanderCoreController/ \
|
||||
Controllers/CorsairDominatorPlatinumController/ \
|
||||
Controllers/CorsairHydroController/ \
|
||||
Controllers/CorsairHydroPlatinumController/ \
|
||||
@@ -110,7 +113,9 @@ INCLUDEPATH +=
|
||||
Controllers/NZXTKrakenController/ \
|
||||
Controllers/OpenRazerController/ \
|
||||
Controllers/PatriotViperController/ \
|
||||
Controllers/PhilipsHueController/ \
|
||||
Controllers/PhilipsWizController/ \
|
||||
Controllers/QMKOpenRGBController/ \
|
||||
Controllers/RazerController/ \
|
||||
Controllers/RedragonController/ \
|
||||
Controllers/RoccatController/ \
|
||||
@@ -128,6 +133,7 @@ INCLUDEPATH +=
|
||||
qt/
|
||||
|
||||
HEADERS += \
|
||||
Controllers/LogitechController/LogitechProtocolCommon.h \
|
||||
dependencies/ColorWheel/ColorWheel.h \
|
||||
dependencies/json/json.hpp \
|
||||
dependencies/libcmmk/include/libcmmk/libcmmk.h \
|
||||
@@ -195,6 +201,8 @@ HEADERS +=
|
||||
Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h \
|
||||
Controllers/CoolerMasterController/RGBController_CMR6000Controller.h \
|
||||
Controllers/CoolerMasterController/RGBController_CMMKController.h \
|
||||
Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h \
|
||||
Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h \
|
||||
Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h \
|
||||
Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h \
|
||||
Controllers/CorsairHydroController/CorsairHydroController.h \
|
||||
@@ -283,6 +291,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 +301,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 \
|
||||
@@ -312,8 +322,12 @@ HEADERS +=
|
||||
Controllers/OpenRazerController/OpenRazerDevices.h \
|
||||
Controllers/PatriotViperController/PatriotViperController.h \
|
||||
Controllers/PatriotViperController/RGBController_PatriotViper.h \
|
||||
Controllers/PhilipsHueController/PhilipsHueController.h \
|
||||
Controllers/PhilipsHueController/RGBController_PhilipsHue.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,8 +381,38 @@ HEADERS +=
|
||||
RGBController/RGBController_Network.h \
|
||||
|
||||
SOURCES += \
|
||||
Controllers/LogitechController/LogitechProtocolCommon.cpp \
|
||||
dependencies/dmiinfo.cpp \
|
||||
dependencies/ColorWheel/ColorWheel.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Action.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/APICache.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/BaseDevice.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/BaseHttpHandler.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Bridge.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/BridgeConfig.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/CLIPSensors.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/ColorUnits.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/EntertainmentMode.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/ExtendedColorHueStrategy.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/ExtendedColorTemperatureStrategy.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Group.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/HueCommandAPI.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/HueDeviceTypes.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/HueException.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Light.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/ModelPictures.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/NewDeviceList.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Scene.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Schedule.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Sensor.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/SimpleBrightnessStrategy.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/SimpleColorHueStrategy.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/SimpleColorTemperatureStrategy.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/StateTransaction.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/TimePattern.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/UPnP.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/Utils.cpp \
|
||||
dependencies/hueplusplus-1.0.0/src/ZLLSensors.cpp \
|
||||
dependencies/libe131/src/e131.c \
|
||||
dependencies/libcmmk/src/libcmmk.c \
|
||||
main.cpp \
|
||||
@@ -439,6 +483,9 @@ SOURCES +=
|
||||
Controllers/CoolerMasterController/RGBController_CMSmallARGBController.cpp \
|
||||
Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp \
|
||||
Controllers/CoolerMasterController/RGBController_CMMKController.cpp \
|
||||
Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp \
|
||||
Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp \
|
||||
Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp \
|
||||
Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.cpp \
|
||||
Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumControllerDetect.cpp \
|
||||
Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.cpp \
|
||||
@@ -562,6 +609,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 +619,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 \
|
||||
@@ -597,9 +646,17 @@ SOURCES +=
|
||||
Controllers/PatriotViperController/PatriotViperController.cpp \
|
||||
Controllers/PatriotViperController/PatriotViperControllerDetect.cpp \
|
||||
Controllers/PatriotViperController/RGBController_PatriotViper.cpp \
|
||||
Controllers/PhilipsHueController/PhilipsHueController.cpp \
|
||||
Controllers/PhilipsHueController/PhilipsHueControllerDetect.cpp \
|
||||
Controllers/PhilipsHueController/PhilipsHueEntertainmentController.cpp \
|
||||
Controllers/PhilipsHueController/RGBController_PhilipsHue.cpp \
|
||||
Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.cpp \
|
||||
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 \
|
||||
@@ -687,6 +744,7 @@ win32:INCLUDEPATH +=
|
||||
dependencies/hidapi \
|
||||
dependencies/inpout32_1501/Win32/ \
|
||||
dependencies/libusb-1.0.22/include \
|
||||
dependencies/mbedtls-2.24.0/include \
|
||||
dependencies/NVFC \
|
||||
dependencies/openrazer-win32 \
|
||||
wmi/ \
|
||||
@@ -694,6 +752,91 @@ win32:INCLUDEPATH +=
|
||||
|
||||
win32:SOURCES += \
|
||||
# dependencies/hidapi/hidapi.c \
|
||||
dependencies/hueplusplus-1.0.0/src/WinHttpHandler.cpp \
|
||||
dependencies/mbedtls-2.24.0/library/aes.c \
|
||||
dependencies/mbedtls-2.24.0/library/aesni.c \
|
||||
dependencies/mbedtls-2.24.0/library/arc4.c \
|
||||
dependencies/mbedtls-2.24.0/library/aria.c \
|
||||
dependencies/mbedtls-2.24.0/library/asn1parse.c \
|
||||
dependencies/mbedtls-2.24.0/library/asn1write.c \
|
||||
dependencies/mbedtls-2.24.0/library/base64.c \
|
||||
dependencies/mbedtls-2.24.0/library/bignum.c \
|
||||
dependencies/mbedtls-2.24.0/library/blowfish.c \
|
||||
dependencies/mbedtls-2.24.0/library/camellia.c \
|
||||
dependencies/mbedtls-2.24.0/library/ccm.c \
|
||||
dependencies/mbedtls-2.24.0/library/certs.c \
|
||||
dependencies/mbedtls-2.24.0/library/chacha20.c \
|
||||
dependencies/mbedtls-2.24.0/library/chachapoly.c \
|
||||
dependencies/mbedtls-2.24.0/library/cipher.c \
|
||||
dependencies/mbedtls-2.24.0/library/cipher_wrap.c \
|
||||
dependencies/mbedtls-2.24.0/library/cmac.c \
|
||||
dependencies/mbedtls-2.24.0/library/ctr_drbg.c \
|
||||
dependencies/mbedtls-2.24.0/library/debug.c \
|
||||
dependencies/mbedtls-2.24.0/library/des.c \
|
||||
dependencies/mbedtls-2.24.0/library/dhm.c \
|
||||
dependencies/mbedtls-2.24.0/library/ecdh.c \
|
||||
dependencies/mbedtls-2.24.0/library/ecdsa.c \
|
||||
dependencies/mbedtls-2.24.0/library/ecjpake.c \
|
||||
dependencies/mbedtls-2.24.0/library/ecp.c \
|
||||
dependencies/mbedtls-2.24.0/library/ecp_curves.c \
|
||||
dependencies/mbedtls-2.24.0/library/entropy.c \
|
||||
dependencies/mbedtls-2.24.0/library/entropy_poll.c \
|
||||
dependencies/mbedtls-2.24.0/library/error.c \
|
||||
dependencies/mbedtls-2.24.0/library/gcm.c \
|
||||
dependencies/mbedtls-2.24.0/library/havege.c \
|
||||
dependencies/mbedtls-2.24.0/library/hkdf.c \
|
||||
dependencies/mbedtls-2.24.0/library/hmac_drbg.c \
|
||||
dependencies/mbedtls-2.24.0/library/md.c \
|
||||
dependencies/mbedtls-2.24.0/library/md2.c \
|
||||
dependencies/mbedtls-2.24.0/library/md4.c \
|
||||
dependencies/mbedtls-2.24.0/library/md5.c \
|
||||
dependencies/mbedtls-2.24.0/library/memory_buffer_alloc.c \
|
||||
dependencies/mbedtls-2.24.0/library/net_sockets.c \
|
||||
dependencies/mbedtls-2.24.0/library/nist_kw.c \
|
||||
dependencies/mbedtls-2.24.0/library/oid.c \
|
||||
dependencies/mbedtls-2.24.0/library/padlock.c \
|
||||
dependencies/mbedtls-2.24.0/library/pem.c \
|
||||
dependencies/mbedtls-2.24.0/library/pk.c \
|
||||
dependencies/mbedtls-2.24.0/library/pk_wrap.c \
|
||||
dependencies/mbedtls-2.24.0/library/pkcs5.c \
|
||||
dependencies/mbedtls-2.24.0/library/pkcs11.c \
|
||||
dependencies/mbedtls-2.24.0/library/pkcs12.c \
|
||||
dependencies/mbedtls-2.24.0/library/pkparse.c \
|
||||
dependencies/mbedtls-2.24.0/library/pkwrite.c \
|
||||
dependencies/mbedtls-2.24.0/library/platform.c \
|
||||
dependencies/mbedtls-2.24.0/library/platform_util.c \
|
||||
dependencies/mbedtls-2.24.0/library/poly1305.c \
|
||||
dependencies/mbedtls-2.24.0/library/psa_crypto.c \
|
||||
dependencies/mbedtls-2.24.0/library/psa_crypto_se.c \
|
||||
dependencies/mbedtls-2.24.0/library/psa_crypto_slot_management.c \
|
||||
dependencies/mbedtls-2.24.0/library/psa_crypto_storage.c \
|
||||
dependencies/mbedtls-2.24.0/library/psa_its_file.c \
|
||||
dependencies/mbedtls-2.24.0/library/ripemd160.c \
|
||||
dependencies/mbedtls-2.24.0/library/rsa.c \
|
||||
dependencies/mbedtls-2.24.0/library/rsa_internal.c \
|
||||
dependencies/mbedtls-2.24.0/library/sha1.c \
|
||||
dependencies/mbedtls-2.24.0/library/sha256.c \
|
||||
dependencies/mbedtls-2.24.0/library/sha512.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_cache.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_ciphersuites.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_cli.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_cookie.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_msg.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_srv.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_ticket.c \
|
||||
dependencies/mbedtls-2.24.0/library/ssl_tls.c \
|
||||
dependencies/mbedtls-2.24.0/library/threading.c \
|
||||
dependencies/mbedtls-2.24.0/library/timing.c \
|
||||
dependencies/mbedtls-2.24.0/library/version.c \
|
||||
dependencies/mbedtls-2.24.0/library/version_features.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509_create.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509_crl.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509_crt.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509_csr.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509write_crt.c \
|
||||
dependencies/mbedtls-2.24.0/library/x509write_csr.c \
|
||||
dependencies/mbedtls-2.24.0/library/xtea.c \
|
||||
dependencies/NVFC/nvapi.cpp \
|
||||
i2c_smbus/i2c_smbus_amdadl.cpp \
|
||||
i2c_smbus/i2c_smbus_i801.cpp \
|
||||
@@ -816,6 +959,9 @@ unix:!macx {
|
||||
LIBS += \
|
||||
-lusb-1.0 \
|
||||
-lstdc++fs \
|
||||
-lmbedx509 \
|
||||
-lmbedcrypto \
|
||||
-lmbedtls \
|
||||
|
||||
#-------------------------------------------------------------------------------------------#
|
||||
# Determine which hidapi to use based on availability #
|
||||
@@ -841,6 +987,7 @@ unix:!macx {
|
||||
}
|
||||
|
||||
SOURCES += \
|
||||
dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \
|
||||
i2c_smbus/i2c_smbus_linux.cpp \
|
||||
serial_port/find_usb_serial_port_linux.cpp \
|
||||
Controllers/FaustusController/RGBController_Faustus.cpp \
|
||||
@@ -890,11 +1037,15 @@ macx {
|
||||
USE_HID_USAGE \
|
||||
|
||||
SOURCES += \
|
||||
dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \
|
||||
serial_port/find_usb_serial_port_linux.cpp \
|
||||
|
||||
LIBS += \
|
||||
-lusb-1.0 \
|
||||
-lhidapi \
|
||||
-lmbedx509 \
|
||||
-lmbedcrypto \
|
||||
-lmbedtls \
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------------------#
|
||||
@@ -914,9 +1065,11 @@ macx:contains(QMAKE_HOST.arch, arm64) {
|
||||
macx:contains(QMAKE_HOST.arch, x86_64) {
|
||||
INCLUDEPATH += \
|
||||
/usr/local/include \
|
||||
/usr/local/homebrew/include \
|
||||
|
||||
LIBS += \
|
||||
-L/usr/local/lib \
|
||||
-L/usr/local/homebrew/lib \
|
||||
}
|
||||
|
||||
DISTFILES += \
|
||||
|
||||
@@ -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
|
||||
@@ -56,8 +58,9 @@ There have been two instances of hardware damage in OpenRGB's development and we
|
||||
* Pre-built binaries in AppImage format are available under the Releases section on GitLab.
|
||||
* You can build the project using Qt Creator or on the command line.
|
||||
1. Install build dependencies
|
||||
- Debian: sudo apt install git build-essential qtcreator qt5-default libusb-1.0-0-dev libhidapi-dev pkgconf
|
||||
- Fedora: sudo dnf install git make automake gcc gcc-c++ qt-creator qt5-devel hidapi-devel libusb-devel
|
||||
- Debian/Ubuntu: `sudo apt install git build-essential qtcreator qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libusb-1.0-0-dev libhidapi-dev pkgconf`
|
||||
- Debian (before `bullseye`) or Ubuntu (before 21.04): `sudo apt install git build-essential qtcreator qt5-default libusb-1.0-0-dev libhidapi-dev pkgconf`
|
||||
- Fedora: `sudo dnf install git make automake gcc gcc-c++ qt-creator qt5-devel hidapi-devel libusb-devel`
|
||||
2. git clone https://gitlab.com/CalcProgrammer1/OpenRGB
|
||||
3. cd OpenRGB
|
||||
4. qmake OpenRGB.pro
|
||||
@@ -184,7 +187,7 @@ There have been two instances of hardware damage in OpenRGB's development and we
|
||||
|
||||
## Projects Used
|
||||
|
||||
* InpOutx64: http://www.highrez.co.uk/downloads/inpout32/
|
||||
* InpOutx64: https://www.highrez.co.uk/downloads/inpout32/
|
||||
* libusb: https://github.com/libusb/libusb
|
||||
* hidapi: https://github.com/libusb/hidapi
|
||||
* libe131: https://github.com/hhromic/libe131
|
||||
@@ -194,6 +197,7 @@ There have been two instances of hardware damage in OpenRGB's development and we
|
||||
* Qt-Plus (ColorWheel): https://github.com/liuyanghejerry/Qt-Plus
|
||||
* AMD ADL Libraries: https://github.com/GPUOpen-LibrariesAndSDKs/display-library
|
||||
* libcmmk: https://github.com/chmod222/libcmmk
|
||||
* hueplusplus: https://github.com/enwi/hueplusplus
|
||||
|
||||
## Projects Researched
|
||||
|
||||
|
||||
+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.61.1) UNRELEASED; urgency=medium
|
||||
|
||||
* Builds from git master. See git history for more information.
|
||||
|
||||
|
||||
Vendored
+1
@@ -11,6 +11,7 @@ Build-Depends:
|
||||
qt5-qmake,
|
||||
libusb-1.0-0-dev,
|
||||
libhidapi-dev,
|
||||
libmbedtls-dev,
|
||||
Homepage: https://gitlab.com/CalcProgrammer1/OpenRGB
|
||||
|
||||
Package: openrgb
|
||||
|
||||
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 "\/-------------------------------------------------------\\"
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
---
|
||||
# Based on Webkit style
|
||||
BasedOnStyle: Webkit
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 120
|
||||
---
|
||||
Language: Cpp
|
||||
Standard: Cpp11
|
||||
# Pointers aligned to the left
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
AccessModifierOffset: -4
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
FixNamespaceComments: true
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
# C++ standard headers (no .h)
|
||||
- Regex: '<[[:alnum:]_-]+>'
|
||||
Priority: 1
|
||||
# Hueplusplus library
|
||||
- Regex: '<hueplusplus/[[:alnum:]_./-]+>'
|
||||
Priority: 2
|
||||
# Extenal libraries (with .h)
|
||||
- Regex: '<[[:alnum:]_./-]+>'
|
||||
Priority: 3
|
||||
# Headers from same folder
|
||||
- Regex: '"[[:alnum:]_.-]+"'
|
||||
Priority: 4
|
||||
# Headers from other folders
|
||||
- Regex: '"[[:alnum:]_/.-]+"'
|
||||
Priority: 5
|
||||
IndentCaseLabels: false
|
||||
NamespaceIndentation: None
|
||||
SortIncludes: true
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpacesInAngles: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
UseTab: Never
|
||||
@@ -0,0 +1,58 @@
|
||||
# Contribution Guide
|
||||
Help is always welcome. If you want to contribute to hueplusplus, please read these guidelines
|
||||
|
||||
## Request feature / Report bug
|
||||
To request a feature or report a bug, create an issue using the templates.
|
||||
|
||||
## Making changes
|
||||
If you want to add a new feature or fix a bug, first check out the development branch and open and closed issues.
|
||||
Maybe the feature already exists and you would just do duplicate work.
|
||||
|
||||
Also use the development branch as the base for your feature branch, because all pull requests are first rebased into development.
|
||||
|
||||
## Pull requests
|
||||
When creating a pull request, be sure to choose development as the target.
|
||||
You might need to rebase on development again and merge in new changes.
|
||||
|
||||
### Keeping up with changes
|
||||
While you are working on your pull request or your forked branch it might occur that
|
||||
someone has force pushed the development branch, from which you started your feature branch.
|
||||
In that case you will need to rebase onto the force pushed branch. For that you need to follow these steps:
|
||||
|
||||
1. Switch to the development branch
|
||||
```
|
||||
git checkout development
|
||||
```
|
||||
2. Add this repository as your remote upstream
|
||||
```
|
||||
git remote add upstream git@github.com:enwi/hueplusplus.git
|
||||
```
|
||||
3. Fetch all changes
|
||||
```
|
||||
git fetch upstream
|
||||
```
|
||||
4. Reset your development branch and replace it with our (force pushed) version
|
||||
```
|
||||
git reset --hard upstream/development
|
||||
```
|
||||
> If you have for some reason made changes to your development branch do a rebase pull to preserve them
|
||||
> ```
|
||||
> git pull --rebase upstream/development
|
||||
> ```
|
||||
5. Switch back to your feature branch
|
||||
```
|
||||
git checkout name-of-your-feature-branch
|
||||
```
|
||||
6. Rebase your changes on to the new development branch
|
||||
```
|
||||
git rebase development
|
||||
```
|
||||
7. Force push your changes (because you are diverged now)
|
||||
```
|
||||
git push --force
|
||||
```
|
||||
|
||||
|
||||
## Code style
|
||||
The code is formatted using clang-format. If you do not want to use it yourself, try to keep your style consistent with the other code
|
||||
so not too many reformats are necessary.
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: 'Status: Available, Type: Bug'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**:
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**:
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**:
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Console log/Error message**:
|
||||
If applicable, add a console log or error message to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. MacOS, Windows, Linux, ESP32 SDK, Arduino]
|
||||
- Version [e.g. 22]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'Status: Available, Type: Enhancement'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# build directory
|
||||
/build*
|
||||
/out
|
||||
/bin
|
||||
|
||||
# Generated documentation
|
||||
/doc/html
|
||||
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.vs
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "lib/mbedtls"]
|
||||
path = lib/mbedtls
|
||||
url = https://github.com/ARMmbed/mbedtls.git
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
language: generic
|
||||
|
||||
env:
|
||||
global:
|
||||
# Ubuntu version
|
||||
- LINUX_DIST=bionic
|
||||
- DEPS_DIR=${TRAVIS_BUILD_DIR}/deps
|
||||
# compiler settings
|
||||
- COMPILER_NAME=gcc
|
||||
- CXX=g++
|
||||
- CC=gcc
|
||||
# Misc
|
||||
- RUN_TESTS=true
|
||||
- COVERAGE=false
|
||||
- PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: bionic
|
||||
sudo: true
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# Misc
|
||||
- python-yaml
|
||||
- doxygen
|
||||
- graphviz
|
||||
before_install:
|
||||
# Combine global build options with OS/compiler-dependent options
|
||||
- export CMAKE_OPTIONS=${CMAKE_OPTIONS}" "${ENV_CMAKE_OPTIONS}
|
||||
- export CXX_FLAGS=${CXX_FLAGS}" "${ENV_CXX_FLAGS}
|
||||
# c++14
|
||||
- sudo apt-get update -qq
|
||||
|
||||
install:
|
||||
# CodeCov
|
||||
- sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-7 90
|
||||
# we have to build lcov on our own, because it is not possible to install lcov-1.13 with apt
|
||||
- wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.13.orig.tar.gz && tar xf lcov_1.13.orig.tar.gz && make -C lcov-1.13 "PREFIX=${HOME}/.local" install && export PATH="${PATH}:${HOME}/.local/bin";
|
||||
# show info
|
||||
- echo ${PATH}
|
||||
- echo ${CXX}
|
||||
- ${CXX} --version
|
||||
- ${CXX} -v
|
||||
- cmake --version
|
||||
- lcov --version
|
||||
|
||||
script:
|
||||
############################################################################
|
||||
# Build main, tests and examples
|
||||
############################################################################
|
||||
- mkdir -p build
|
||||
- cd build
|
||||
- cmake .. -Dhueplusplus_TESTS=ON -DCMAKE_BUILD_TYPE=Debug -Dhueplusplus_EXAMPLES=ON
|
||||
- make hueplusplus_examples hueplusplus_snippets
|
||||
- make coveragetest
|
||||
- cd ..
|
||||
- doxygen Doxyfile
|
||||
# .nojekyll file prevents hiding of files starting with _
|
||||
- touch doc/html/.nojekyll
|
||||
|
||||
|
||||
after_success:
|
||||
# upload result to codecov
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
deploy:
|
||||
provider: pages
|
||||
skip_cleanup: true
|
||||
local_dir: doc/html
|
||||
github_token: $GH_REPO_TOKEN
|
||||
on:
|
||||
branch: master
|
||||
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.11)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.11)
|
||||
endif()
|
||||
|
||||
# Add cmake dir to module path, so Find*.cmake can be found
|
||||
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||
|
||||
project(hueplusplus VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
# check whether hueplusplus is compiled directly or included as a subdirectory
|
||||
if(NOT DEFINED hueplusplus_master_project)
|
||||
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set(hueplusplus_master_project ON)
|
||||
else()
|
||||
set(hueplusplus_master_project OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# options to set
|
||||
option(hueplusplus_TESTS "Build tests" OFF)
|
||||
option(hueplusplus_EXAMPLES "Build examples" OFF)
|
||||
|
||||
option(CLANG_TIDY_FIX "Perform fixes for Clang-Tidy" OFF)
|
||||
find_program(CLANG_TIDY_EXE NAMES "clang-tidy" DOC "Path to clang-tidy executable")
|
||||
if(CLANG_TIDY_EXE)
|
||||
if(CLANG_TIDY_FIX)
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-fix")
|
||||
else()
|
||||
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# update submodules
|
||||
find_package(Git QUIET)
|
||||
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
|
||||
option(GIT_SUBMODULE "Check submodules during build" ON)
|
||||
if(GIT_SUBMODULE)
|
||||
message(STATUS "Submodule update")
|
||||
execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
RESULT_VARIABLE GIT_SUBMOD_RESULT)
|
||||
if(NOT GIT_SUBMOD_RESULT EQUAL "0")
|
||||
message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Set default build type if none was specified
|
||||
set(default_build_type "Release")
|
||||
if(hueplusplus_master_project AND (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES))
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
|
||||
# Set possible values for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
|
||||
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif()
|
||||
|
||||
|
||||
# get the correct installation directory for add_library() to work
|
||||
if(WIN32 AND NOT CYGWIN)
|
||||
set(DEF_INSTALL_CMAKE_DIR cmake)
|
||||
else()
|
||||
set(DEF_INSTALL_CMAKE_DIR lib/cmake/hueplusplus)
|
||||
endif()
|
||||
set(INSTALL_CMAKE_DIR ${DEF_INSTALL_CMAKE_DIR} CACHE PATH "Installation directory for CMake files")
|
||||
|
||||
# target for uninstall
|
||||
if(NOT TARGET uninstall)
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||
IMMEDIATE @ONLY)
|
||||
|
||||
add_custom_target(uninstall
|
||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||
endif()
|
||||
|
||||
# if we are on a apple machine this is needed
|
||||
if (1 AND APPLE)
|
||||
set(CMAKE_MACOSX_RPATH 1)
|
||||
endif()
|
||||
|
||||
set(USE_STATIC_MBEDTLS_LIBRARY ON)
|
||||
set(USE_SHARED_MBEDTLS_LIBRARY OFF)
|
||||
add_subdirectory("lib/mbedtls" EXCLUDE_FROM_ALL)
|
||||
|
||||
# Compile the mbedtls library as a static with position independent code,
|
||||
# because we need it for both a shared and static library
|
||||
set_property(TARGET mbedtls PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET mbedcrypto PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET mbedx509 PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
# if the user decided to use tests add the subdirectory
|
||||
if(hueplusplus_TESTS)
|
||||
add_subdirectory("test")
|
||||
endif()
|
||||
|
||||
if(hueplusplus_EXAMPLES)
|
||||
add_subdirectory("examples")
|
||||
endif()
|
||||
+2612
File diff suppressed because it is too large
Load Diff
+55
@@ -0,0 +1,55 @@
|
||||
timestamps {
|
||||
node('master')
|
||||
{
|
||||
stage('SCM')
|
||||
{
|
||||
checkout scm
|
||||
}
|
||||
stage('Build')
|
||||
{
|
||||
sh returnStatus: true, script: 'rm -r build'
|
||||
sh '''#!/bin/bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -Dhueplusplus_TESTS=ON
|
||||
make -j8 2>&1 | tee buildlog.txt
|
||||
test ${PIPESTATUS[0]} -eq 0'''
|
||||
}
|
||||
stage('Test')
|
||||
{
|
||||
sh '''cd build
|
||||
hueplusplus/test/test_HuePlusPlus --gtest_output=xml:test.xml
|
||||
make -j8 coveragetest'''
|
||||
step([$class: 'XUnitBuilder', testTimeMargin: '3000', thresholdMode: 1,
|
||||
thresholds: [
|
||||
[$class: 'FailedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: ''],
|
||||
[$class: 'SkippedThreshold', failureNewThreshold: '', failureThreshold: '', unstableNewThreshold: '', unstableThreshold: '']
|
||||
],
|
||||
tools: [
|
||||
[$class: 'GoogleTestType', deleteOutputFiles: true, failIfNotNew: true, pattern: 'build/test.xml', skipNoTestFiles: false, stopProcessingIfError: true]
|
||||
]
|
||||
])
|
||||
publishHTML(
|
||||
[allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'build/coveragetest', reportFiles: 'index.html', reportName: 'Coveragetest', reportTitles: '']
|
||||
)
|
||||
}
|
||||
stage('CppCheck')
|
||||
{
|
||||
sh 'cppcheck -j 8 --force -ihueplusplus/test -ihueplusplus/jsoncpp.cpp hueplusplus/ 2>build/CppCheckResult'
|
||||
rtp nullAction: '1', parserName: 'HTML', stableText: '${FILE:build/CppCheckResult}'
|
||||
}
|
||||
stage('Documentation')
|
||||
{
|
||||
sh 'doxygen Doxyfile'
|
||||
publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'doc/html/', reportFiles: 'index.html', reportName: 'Doxygen'])
|
||||
}
|
||||
stage('Parse warnings')
|
||||
{
|
||||
warnings canComputeNew: false, canResolveRelativePaths: false, categoriesPattern: '', defaultEncoding: '', excludePattern: '', healthy: '', includePattern: '', messagesPattern: '', parserConfigurations: [[parserName: 'Doxygen', pattern: 'doxylog.txt']], unHealthy: ''
|
||||
sh returnStatus: true, script: 'rm doxylog.txt'
|
||||
warnings canComputeNew: false, canResolveRelativePaths: false, categoriesPattern: '', defaultEncoding: '', excludePattern: '', healthy: '', includePattern: '', messagesPattern: '', parserConfigurations: [[parserName: 'GNU C Compiler 4 (gcc)', pattern: 'build/buildlog.txt']], unHealthy: ''
|
||||
sh returnStatus: true, script: 'rm build/buildlog.txt'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
# hueplusplus
|
||||
A simple and easy to use library for Philips Hue Lights
|
||||
|
||||
| Branch | Travis CI | Codecov | LGTM
|
||||
|:-|:-|:-|:-|
|
||||
| [Master](https://github.com/enwi/hueplusplus/tree/master) | [](https://travis-ci.com/enwi/hueplusplus) | [](https://codecov.io/gh/enwi/hueplusplus) | [](https://lgtm.com/projects/g/enwi/hueplusplus/context:cpp) |
|
||||
| [Development](https://github.com/enwi/hueplusplus/tree/development) | [](https://travis-ci.com/enwi/hueplusplus) | [](https://codecov.io/gh/enwi/hueplusplus) | |
|
||||
|
||||
## Features
|
||||
* find bridges with SSDP or set an ip manually
|
||||
* all common light functions (brightness, color, temperature)
|
||||
* extended alert() functions, which alert in a specific color (good for notifications)
|
||||
* supports sensors, rules, groups, scenes and schedules
|
||||
* streaming with entertainment mode
|
||||
* [documented with doxygen](https://enwi.github.io/hueplusplus/)
|
||||
* tested with google test, google mock and gcov/lcov
|
||||
|
||||
## Compatibility
|
||||
* Linux
|
||||
* Windows
|
||||
* MacOS
|
||||
* Espressif ESP32 SDK & Arduino
|
||||
|
||||
## How to use
|
||||
### <a name="searchingBridges"></a>Searching for Bridges
|
||||
To start searching for a Hue Bridge you will need to choose an IHttpHandler and create one. The options are a "WinHttpHandler" (for windows) or a "LinHttpHandler" (for linux).
|
||||
Then create a BridgeFinder object with the handler.
|
||||
The handler is needed, because it tells the finder which functions to use to communicate with a bridge or your local network.
|
||||
After that you can call findBridges(), which will return a vector containing the ip and mac address of all found Bridges.
|
||||
```C++
|
||||
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
|
||||
handler = std::make_shared<hueplusplus::LinHttpHandler>();
|
||||
hueplusplus::BridgeFinder finder(handler);
|
||||
std::vector<hueplusplus::BridgeFinder::BridgeIdentification> bridges = finder.findBridges();
|
||||
if (bridges.empty())
|
||||
{
|
||||
std::cerr << "No bridges found\n";
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Authenticate Bridges
|
||||
If you have found the Bridge you were looking for, you can then move on with the authentication process.
|
||||
To get a new username from the Bridge (for now) you simply call getBridge(bridges[\<index\>]),
|
||||
where index is your preferred Bridge from the part [Searching for Bridges](#searchingBridges).
|
||||
```C++
|
||||
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
|
||||
```
|
||||
If you on the other hand already have a username you can add your bridge like so
|
||||
```C++
|
||||
finder.addUsername(bridges[0].mac, "<username>");
|
||||
hueplusplus::Bridge bridge = finder.getBridge(bridges[0]);
|
||||
```
|
||||
If you do not want to use the BridgeFinder or you already know the ip and username of your bridge you have the option to create your own Bridge object.
|
||||
Here you will need to provide the ip address, the port number, a username and an HttpHandler
|
||||
```C++
|
||||
// For windows use std::make_shared<hueplusplus::WinHttpHandler>();
|
||||
handler = std::make_shared<hueplusplus::LinHttpHandler>();
|
||||
hueplusplus::Bridge bridge("192.168.2.102", 80, "<username>", handler);
|
||||
```
|
||||
|
||||
### Controlling lights
|
||||
If you have your Bridge all set up, you can now control its lights.
|
||||
For that create a new Light object and call lights().get(\<id\>) on your bridge object to get a reference to a specific light, where id
|
||||
is the id of the light set internally by the Hue Bridge.
|
||||
```C++
|
||||
hueplusplus::Light light1 = bridge.lights().get(1);
|
||||
```
|
||||
If you don't know the id of a specific light or want to get an overview over all lights that are controlled by your bridge,
|
||||
you can get a vector containing them by calling getAll(). If no lights are found the vector will be empty.
|
||||
```C++
|
||||
std::vector<hueplusplus::Light> lights = bridge.lights().getAll();
|
||||
```
|
||||
If you now want to control a light, call a specific function of it.
|
||||
```C++
|
||||
light1.on();
|
||||
light1.setBrightness(120);
|
||||
light1.alertHueSaturation(25500, 255);
|
||||
light1.setColorLoop(true);
|
||||
light1.setColorRGB(255, 128, 0);
|
||||
lights[1].off();
|
||||
lights.at(1).setColorHue(4562);
|
||||
```
|
||||
But keep in mind that some light types do not have all functions available. So you might call a
|
||||
specific function, but nothing will happen. For that you might want to check what type
|
||||
of a light you are controlling. For that you can call the function getColorType(), which will return
|
||||
a ColorType.
|
||||
```C++
|
||||
hueplusplus::ColorType type1 = light1.getColorType();
|
||||
```
|
||||
There's also a new way to check whether specific functions of a light are available:
|
||||
```C++
|
||||
light1.hasBrightnessControl();
|
||||
light1.hasTemperatureControl();
|
||||
light1.hasColorControl();
|
||||
```
|
||||
These will either return true(light has specified function) or false(light lacks specified function).
|
||||
|
||||
### Further reading
|
||||
If you want to know more about all functions just look inside the doxygen documentation. It can be found [here](https://enwi.github.io/hueplusplus/)
|
||||
|
||||
## Build and install
|
||||
### Basic installation
|
||||
If you want to build the library you can use cmake (at least version 3.8). First create a build folder and then execute cmake.
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
```
|
||||
Then compile the code with make. If you are inpatient use the option -j\<number\>, where number specifies how many files are compiled at the same time. Note this number should not exceed the number of cores*2 of your machine.
|
||||
```bash
|
||||
make
|
||||
```
|
||||
```bash
|
||||
make -j4
|
||||
```
|
||||
If you want to install the library use
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
To remove it
|
||||
```bash
|
||||
make uninstall
|
||||
```
|
||||
|
||||
### Advanced usage
|
||||
If you have a project that already uses CMake you probably want to add the hueplusplus library directly in your cmake file.
|
||||
For that the best way is to use find_package().
|
||||
When cmake finds the hueplusplus library you can then link against either the shared or static version of the library.
|
||||
```cmake
|
||||
find_package(hueplusplus REQUIRED)
|
||||
|
||||
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
|
||||
```
|
||||
But this will only work if the hueplusplus library is already installed.
|
||||
To get around this problem there is a pretty awesome way.
|
||||
If you have the hueplusplus repository included in your project repository (as a submodule) or know where the folder lives you can do the following:
|
||||
```cmake
|
||||
find_package(hueplusplus QUIET)
|
||||
if(NOT hueplusplus_FOUND)
|
||||
message(STATUS "-- hueplusplus not found, building it")
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/<path to directory>/hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus")
|
||||
endif()
|
||||
|
||||
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
|
||||
```
|
||||
This will check if the hueplusplus library was found by find_package() and if not it will use the specified path to the library source and compile it during the build process.
|
||||
|
||||
### Running tests
|
||||
If you additionally want to run the tests use cmake with the option -Dhueplusplus_TESTS=ON. Testing is done with Google gtest and gmock. Note that you wont need to install gtest/gmock yourself, because cmake will automatically download them and include them during the build. Since I added a custom target you will only need to call "make unittest" and the tests are compiled and executed.
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -Dhueplusplus_TESTS=ON
|
||||
make unittest
|
||||
```
|
||||
If you also want to execute coverage tests you will need to install gcov and lcov yourself. To run the coverage test use
|
||||
```bash
|
||||
make coveragetest
|
||||
```
|
||||
|
||||
|
||||
## Copyright
|
||||
Copyright (c) 2017 Jan Rogall & Moritz Wirger. See LICENSE for further details.
|
||||
@@ -0,0 +1,21 @@
|
||||
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||
|
||||
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||
foreach(file ${files})
|
||||
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
exec_program(
|
||||
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||
OUTPUT_VARIABLE rm_out
|
||||
RETURN_VALUE rm_retval
|
||||
)
|
||||
if(NOT "${rm_retval}" STREQUAL 0)
|
||||
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||
endif(NOT "${rm_retval}" STREQUAL 0)
|
||||
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||
endforeach(file)
|
||||
@@ -0,0 +1,7 @@
|
||||
# -config file of the hueplusplus package
|
||||
# It defines the following
|
||||
# hueplusplus_FOUND - which indicates that the module was found
|
||||
# hueplusplus_INCLUDE_DIR
|
||||
|
||||
set(hueplusplus_FOUND TRUE)
|
||||
set(hueplusplus_INCLUDE_DIR "@INSTALL_INCLUDE_DIR@")
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
ignore:
|
||||
- "/usr/**/*" # ingnore all unix system ressources
|
||||
- "**/json*.*" # ignore all json files
|
||||
- "**/hueplusplus/include/json/*" # ignore all files in json folder
|
||||
- "**/hueplusplus/test/*" # ignore all files in test folder
|
||||
- "**/hueplusplus/build/**/*" # ignore all files in build folder
|
||||
- "**/test/**/*" # ignore all files in test folders
|
||||
- "**/v1/**/*" # ignore all macros files
|
||||
@@ -0,0 +1,86 @@
|
||||
# Build and install {#build}
|
||||
|
||||
[TOC]
|
||||
|
||||
# Basic installation {#basic-install}
|
||||
|
||||
## Clone from github {#clone}
|
||||
To get the newest version of the hueplusplus library, clone it directly from [github](https://github.com/enwi/hueplusplus).
|
||||
The master branch contains the latest tested and stable version, while the development branch is more unstable.
|
||||
```{.sh}
|
||||
~ $ git clone https://github.com/enwi/hueplusplus.git
|
||||
```
|
||||
This creates a folder hueplusplus with the library sources.
|
||||
|
||||
When you want to update the library for a new version, use pull with rebase.
|
||||
```{.sh}
|
||||
~/hueplusplus $ git pull --rebase
|
||||
```
|
||||
|
||||
## Build with CMake {#build-cmake}
|
||||
To build the library, you need to use [CMake](https://cmake.org) version 3.8 or higher.
|
||||
It is easiest to create a separate build directory where the build files are stored.
|
||||
```{.sh}
|
||||
~/hueplusplus $ mkdir build
|
||||
~/hueplusplus $ cd build
|
||||
~/hueplusplus/build $ cmake ..
|
||||
~/hueplusplus/build $ make
|
||||
```
|
||||
|
||||
To install or uninstall the library use the make targets.
|
||||
```{.sh}
|
||||
~/hueplusplus/build $ make install
|
||||
~/hueplusplus/build $ make uninstall
|
||||
```
|
||||
|
||||
## Use in a CMake project {#import-cmake}
|
||||
If you have a project that already uses CMake you probably want to add the hueplusplus library directly in your cmake file.
|
||||
For that the best way is to use find_package().
|
||||
```{.cmake}
|
||||
find_package(hueplusplus REQUIRED)
|
||||
```
|
||||
But this will only work if the hueplusplus library is already installed.
|
||||
Instead, if you have the hueplusplus repository included in your project repository (as a submodule) or know where the folder lives you can do the following:
|
||||
```{.cmake}
|
||||
find_package(hueplusplus QUIET)
|
||||
if(NOT hueplusplus_FOUND)
|
||||
message(STATUS "-- hueplusplus not found, building it")
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/<path to directory>/hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus")
|
||||
endif()
|
||||
```
|
||||
This will check if the hueplusplus library was found by find_package() and if not it will use the specified path to the library source and compile it during the build process.
|
||||
|
||||
The cmake project defines two library targets: `hueplusplusstatic` to link as a static library and `hueplusplusshared` to link as a shared library.
|
||||
```{.cmake}
|
||||
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
|
||||
```
|
||||
|
||||
## Use in another project {#import-other}
|
||||
When you are not using CMake, you have to install hueplusplus and change your build configuration to link to the compiled library.
|
||||
The header files in the include directory need to be added to the include path.
|
||||
How you do this depends on the build system.
|
||||
|
||||
## Building tests {#build-tests}
|
||||
If you additionally want to run the tests use cmake with the option -Dhueplusplus_TESTS=ON. Testing is done with Google gtest and gmock. Note that you wont need to install gtest/gmock yourself, because cmake will automatically download them and include them during the build.
|
||||
The custom target `unittest` compiles and executes all tests.
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -Dhueplusplus_TESTS=ON
|
||||
make unittest
|
||||
```
|
||||
|
||||
If you also want to execute coverage tests you will need to install gcov and lcov yourself. To run the coverage test use
|
||||
```bash
|
||||
make coveragetest
|
||||
```
|
||||
|
||||
## Building examples {#build-examples}
|
||||
There are some small [example programs](@ref examples) using this library in the examples folder. To build them,
|
||||
set `hueplusplus_EXAMPLES=ON`. The target `hueplusplus_examples` builds all examples into build/examples.
|
||||
```{.sh}
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -Dhueplusplus_EXAMPLES=ON
|
||||
make hueplusplus_examples
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
# Getting started {#getting-started}
|
||||
|
||||
## Creating the Hue bridge
|
||||
To start searching for a Hue Bridge you will need to choose an IHttpHandler and create one.
|
||||
The options are a [WinHttpHandler](@ref hueplusplus::WinHttpHandler) (for windows) or a [LinHttpHandler](@ref hueplusplus::LinHttpHandler) (for linux or linux-like).
|
||||
|
||||
Then create a [BridgeFinder](@ref hueplusplus::BridgeFinder) object with the handler.
|
||||
The handler is needed, because it tells the finder which functions to use to communicate with a bridge or your local network.
|
||||
After that you can call [findBridges()](@ref hueplusplus::BridgeFinder::findBridges), which will return a vector containing the ip and mac address of all found Bridges.
|
||||
\snippet Snippets.cpp search-bridge
|
||||
|
||||
## Authenticate Bridges
|
||||
If you have found the Bridge you were looking for, you can then move on with the authentication process.
|
||||
To get a new username from the Bridge (for now) you simply call [getBridge(bridges[\<index\>])](@ref hueplusplus::BridgeFinder::getBridge),
|
||||
where index is your preferred Bridge from the part [Searching for Bridges](#searchingBridges). This requires the user to press the link button.
|
||||
\snippet Snippets.cpp get-bridge-1
|
||||
|
||||
If you on the other hand already have a username you can add your bridge like so
|
||||
\snippet Snippets.cpp get-bridge-2
|
||||
|
||||
If you do not want to use the BridgeFinder or you already know the ip and username of your bridge you have the option to create your own Hue object.
|
||||
Here you will need to provide the ip address, the port number, a username and an HttpHandler
|
||||
\snippet Snippets.cpp get-bridge-3
|
||||
|
||||
At this point you may want to decide whether to use a [shared state](@ref shared-state) cache model or keep the default settings.
|
||||
|
||||
### Controlling lights
|
||||
|
||||
\snippet Snippets.cpp control-lights
|
||||
|
||||
Use [transactions](@ref transactions) to change multiple properties at once.
|
||||
|
||||
### Controlling groups
|
||||
|
||||
\snippet Snippets.cpp control-groups
|
||||
|
||||
## More information
|
||||
- [Transactions](@ref transactions)
|
||||
- [Shared state cache](@ref shared-state)
|
||||
@@ -0,0 +1,139 @@
|
||||
# Documentation for the hueplusplus library
|
||||
A simple and easy to use library for Philips Hue Lights.
|
||||
|
||||
[TOC]
|
||||
|
||||
## Features
|
||||
* find bridges with SSDP or set an ip manually
|
||||
* all common light functions (brightness, color, temperature)
|
||||
* extended alert() functions, which alert in a specific color (good for notifications)
|
||||
* supports sensors, rules, groups, scenes and schedules
|
||||
* streaming with entertainment mode
|
||||
* documented with doxygen
|
||||
* tested with google test, google mock and gcov/lcov
|
||||
|
||||
## Compatibility
|
||||
* Linux
|
||||
* Windows
|
||||
* MacOS
|
||||
* Espressif ESP32 SDK & Arduino
|
||||
|
||||
## How to use
|
||||
[Getting started](@ref getting-started)
|
||||
### Searching for Bridges
|
||||
To start searching for a Hue Bridge you will need to choose an IHttpHandler and create one. The options are a [WinHttpHandler](@ref hueplusplus::WinHttpHandler) (for windows) or a [LinHttpHandler](@ref hueplusplus::LinHttpHandler) (for linux or linux-like).
|
||||
|
||||
Then create a [BridgeFinder](@ref hueplusplus::BridgeFinder) object with the handler.
|
||||
The handler is needed, because it tells the finder which functions to use to communicate with a bridge or your local network.
|
||||
After that you can call [findBridges()](@ref hueplusplus::BridgeFinder::findBridges), which will return a vector containing the ip and mac address of all found Bridges.
|
||||
\snippet Snippets.cpp search-bridge
|
||||
|
||||
At this point you may want to decide whether to use a [shared state](@ref shared-state) cache model or keep the default settings.
|
||||
|
||||
### Authenticate Bridges
|
||||
If you have found the Bridge you were looking for, you can then move on with the authentication process.
|
||||
To get a new username from the Bridge (for now) you simply call [getBridge(bridges[\<index\>])](@ref hueplusplus::BridgeFinder::getBridge),
|
||||
where index is your preferred Bridge from the part [Searching for Bridges](#searchingBridges). This requires the user to press the link button.
|
||||
\snippet Snippets.cpp get-bridge-1
|
||||
|
||||
If you on the other hand already have a username you can add your bridge like so
|
||||
\snippet Snippets.cpp get-bridge-2
|
||||
|
||||
If you do not want to use the BridgeFinder or you already know the ip and username of your bridge you have the option to create your own Bridge object.
|
||||
Here you will need to provide the ip address, the port number, a username and an HttpHandler
|
||||
\snippet Snippets.cpp get-bridge-3
|
||||
|
||||
|
||||
### Controlling lights
|
||||
If you have your Bridge all set up, you can now control its lights.
|
||||
For that create a new Light object and call [lights().get(\<id\>)](@ref hueplusplus::ResourceList::get) on your bridge object to get a reference to a specific light, where id
|
||||
is the id of the light set internally by the Hue Bridge.
|
||||
\snippet Snippets.cpp light-1
|
||||
|
||||
If you don't know the id of a specific light or want to get an overview over all lights that are controlled by your bridge,
|
||||
you can get a vector containing them by calling [getAll()](@ref hueplusplus::ResourceList::getAll) on your bridge object. If no lights are found the vector will be empty.
|
||||
\snippet Snippets.cpp light-2
|
||||
|
||||
If you now want to control a light, call a specific function of it.
|
||||
\snippet Snippets.cpp light-3
|
||||
|
||||
But keep in mind that some light types do not have all functions available. So you might call a
|
||||
specific function, but nothing will happen. For that you might want to check what type
|
||||
of a light you are controlling. For that you can call the function [getColorType()](@ref hueplusplus::Light::getColorType()), which will return
|
||||
a ColorType.
|
||||
\snippet Snippets.cpp light-4
|
||||
|
||||
There's also a new way to check whether specific functions of a light are available:
|
||||
\snippet Snippets.cpp light-5
|
||||
|
||||
These will either return true(light has specified function) or false(light lacks specified function).
|
||||
|
||||
## Build and install
|
||||
[Build and install guide](@ref build)
|
||||
|
||||
### Basic installation
|
||||
If you want to build the library you can use cmake (at least version 3.8). First create a build folder and then execute cmake.
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
```
|
||||
Then compile the code with make. If you are inpatient use the option -j\<number\>, where number specifies how many files are compiled at the same time. Note this number should not exceed the number of cores*2 of your machine.
|
||||
```bash
|
||||
make
|
||||
```
|
||||
```bash
|
||||
make -j4
|
||||
```
|
||||
If you want to install the library use
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
To remove it
|
||||
```bash
|
||||
make uninstall
|
||||
```
|
||||
|
||||
### Advanced usage
|
||||
If you have a project that already uses CMake you probably want to add the hueplusplus library directly in your cmake file.
|
||||
For that the best way is to use find_package().
|
||||
When cmake finds the hueplusplus library you can then link against either the shared or static version of the library.
|
||||
```cmake
|
||||
find_package(hueplusplus REQUIRED)
|
||||
|
||||
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
|
||||
```
|
||||
But this will only work if the hueplusplus library is already installed.
|
||||
To get around this problem there is a pretty awesome way.
|
||||
If you have the hueplusplus repository included in your project repository (as a submodule) or know where the folder lives you can do the following:
|
||||
```cmake
|
||||
find_package(hueplusplus QUIET)
|
||||
if(NOT hueplusplus_FOUND)
|
||||
message(STATUS "-- hueplusplus not found, building it")
|
||||
add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/<path to directory>/hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus")
|
||||
endif()
|
||||
|
||||
target_link_libraries(<executable> PUBLIC hueplusplusstatic)
|
||||
```
|
||||
This will check if the hueplusplus library was found by find_package() and if not it will use the specified path to the library source and compile it during the build process.
|
||||
|
||||
### Running tests
|
||||
If you additionally want to run the tests use cmake with the option -Dhueplusplus_TESTS=ON. Testing is done with Google gtest and gmock. Note that you wont need to install gtest/gmock yourself, because cmake will automatically download them and include them during the build. Since I added a custom target you will only need to call "make unittest" and the tests are compiled and executed.
|
||||
```bash
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -Dhueplusplus_TESTS=ON
|
||||
make unittest
|
||||
```
|
||||
If you also want to execute coverage tests you will need to install gcov and lcov yourself. To run the coverage test use
|
||||
```bash
|
||||
make coveragetest
|
||||
```
|
||||
|
||||
|
||||
## Other pages
|
||||
- [Getting started](@ref getting-started)
|
||||
- [Build and install](@ref build)
|
||||
- [Shared state cache](@ref shared-state)
|
||||
- [Transactions](@ref transactions)
|
||||
- [Sensors](@ref sensors)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user